1b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
2b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*******************************************************************************
3b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   Copyright (C) 2010-2011, International Business Machines
4b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   Corporation and others.  All Rights Reserved.
5b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*******************************************************************************
6b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   file name:  bytetrietest.cpp
7b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   encoding:   US-ASCII
8b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   tab size:   8 (not used)
9b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   indentation:4
10b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*
11b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   created on: 2010nov16
12b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   created by: Markus W. Scherer
13b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*/
14b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
15b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include <string.h>
16b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
17b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/utypes.h"
18b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/bytestrie.h"
19b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/bytestriebuilder.h"
20b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/localpointer.h"
21b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/stringpiece.h"
22b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "intltest.h"
23b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
24b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
25b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
26b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostruct StringAndValue {
27b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const char *s;
28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t value;
29b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
30b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass BytesTrieTest : public IntlTest {
32b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrieTest();
34b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~BytesTrieTest();
35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
36b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=NULL);
37b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestBuilder();
38b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestEmpty();
39b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void Test_a();
40b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void Test_a_ab();
41b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestShortestBranch();
42b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestBranches();
43b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestLongSequence();
44b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestLongBranch();
45b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestValuesForState();
46b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestCompact();
47b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
48b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie *buildMonthsTrie(UStringTrieBuildOption buildOption);
49b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestHasUniqueValue();
50b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestGetNextBytes();
51b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestIteratorFromBranch();
52b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestIteratorFromLinearMatch();
53b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestTruncatingIteratorFromRoot();
54b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestTruncatingIteratorFromLinearMatchShort();
55b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestTruncatingIteratorFromLinearMatchLong();
56b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void TestIteratorFromBytes();
57b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
58b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void checkData(const StringAndValue data[], int32_t dataLength);
59b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void checkData(const StringAndValue data[], int32_t dataLength, UStringTrieBuildOption buildOption);
60b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie *buildTrie(const StringAndValue data[], int32_t dataLength,
61b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         UStringTrieBuildOption buildOption);
62b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void checkFirst(BytesTrie &trie, const StringAndValue data[], int32_t dataLength);
63b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void checkNext(BytesTrie &trie, const StringAndValue data[], int32_t dataLength);
64b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void checkNextWithState(BytesTrie &trie, const StringAndValue data[], int32_t dataLength);
65b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void checkNextString(BytesTrie &trie, const StringAndValue data[], int32_t dataLength);
66b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void checkIterator(const BytesTrie &trie, const StringAndValue data[], int32_t dataLength);
67b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void checkIterator(BytesTrie::Iterator &iter, const StringAndValue data[], int32_t dataLength);
68b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
69b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
70b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrieBuilder *builder_;
71b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
72b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
73b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoextern IntlTest *createBytesTrieTest() {
74b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return new BytesTrieTest();
75b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
76b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
77b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoBytesTrieTest::BytesTrieTest() : builder_(NULL) {
78b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "BytesTrieTest()");
79b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    builder_=new BytesTrieBuilder(errorCode);
80b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
81b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
82b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoBytesTrieTest::~BytesTrieTest() {
83b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete builder_;
84b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
85b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
86b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) {
87b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(exec) {
88b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        logln("TestSuite BytesTrieTest: ");
89b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
90b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO_BEGIN;
91b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestBuilder);
92b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestEmpty);
93b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(Test_a);
94b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(Test_a_ab);
95b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestShortestBranch);
96b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestBranches);
97b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestLongSequence);
98b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestLongBranch);
99b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestValuesForState);
100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestCompact);
101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestHasUniqueValue);
102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestGetNextBytes);
103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestIteratorFromBranch);
104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestIteratorFromLinearMatch);
105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestTruncatingIteratorFromRoot);
106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestTruncatingIteratorFromLinearMatchShort);
107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestTruncatingIteratorFromLinearMatchLong);
108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO(TestIteratorFromBytes);
109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TESTCASE_AUTO_END;
110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestBuilder() {
113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "TestBuilder()");
114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    builder_->clear();
115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete builder_->build(USTRINGTRIE_BUILD_FAST, errorCode);
116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(errorCode.reset()!=U_INDEX_OUTOFBOUNDS_ERROR) {
117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("BytesTrieBuilder().build() did not set U_INDEX_OUTOFBOUNDS_ERROR");
118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // TODO: remove .build(...) once add() checks for duplicates.
121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    builder_->add("=", 0, errorCode).add("=", 1, errorCode).build(USTRINGTRIE_BUILD_FAST, errorCode);
122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(errorCode.reset()!=U_ILLEGAL_ARGUMENT_ERROR) {
123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("BytesTrieBuilder.add() did not detect duplicates");
124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestEmpty() {
129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "", 0 }
131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkData(data, LENGTHOF(data));
133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::Test_a() {
136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "a", 1 }
138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkData(data, LENGTHOF(data));
140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::Test_a_ab() {
143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "a", 1 },
145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "ab", 100 }
146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkData(data, LENGTHOF(data));
148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestShortestBranch() {
151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "a", 1000 },
153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "b", 2000 }
154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkData(data, LENGTHOF(data));
156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestBranches() {
159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "a", 0x10 },
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "cc", 0x40 },
162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "e", 0x100 },
163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "ggg", 0x400 },
164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "i", 0x1000 },
165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "kkkk", 0x4000 },
166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "n", 0x10000 },
167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "ppppp", 0x40000 },
168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "r", 0x100000 },
169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "sss", 0x200000 },
170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "t", 0x400000 },
171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "uu", 0x800000 },
172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "vv", 0x7fffffff },
173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "zz", 0x80000000 }
174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t length=2; length<=LENGTHOF(data); ++length) {
176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        infoln("TestBranches length=%d", (int)length);
177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        checkData(data, length);
178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestLongSequence() {
182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "a", -1 },
184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // sequence of linear-match nodes
185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", -2 },
186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // more than 256 bytes
187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", -3 }
193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkData(data, LENGTHOF(data));
195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestLongBranch() {
198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Split-branch and interesting compact-integer values.
199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "a", -2 },
201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "b", -1 },
202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "c", 0 },
203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "d2", 1 },
204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "f", 0x3f },
205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "g", 0x40 },
206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "h", 0x41 },
207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "j23", 0x1900 },
208b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "j24", 0x19ff },
209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "j25", 0x1a00 },
210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "k2", 0x1a80 },
211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "k3", 0x1aff },
212b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "l234567890", 0x1b00 },
213b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "l234567890123", 0x1b01 },
214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", 0x10ffff },
215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "oooooooooooooooooooooooooooooooooooooooooooooooooooooo", 0x110000 },
216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "pppppppppppppppppppppppppppppppppppppppppppppppppppppp", 0x120000 },
217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "r", 0x333333 },
218b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "s2345", 0x4444444 },
219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "t234567890", 0x77777777 },
220b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "z", 0x80000001 }
221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkData(data, LENGTHOF(data));
223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestValuesForState() {
226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Check that saveState() and resetToState() interact properly
227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // with next() and current().
228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "a", -1 },
230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "ab", -2 },
231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abc", -3 },
232b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcd", -4 },
233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcde", -5 },
234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcdef", -6 }
235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkData(data, LENGTHOF(data));
237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
239b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestCompact() {
240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Duplicate trailing strings and values provide opportunities for compacting.
241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "+", 0 },
243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "+august", 8 },
244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "+december", 12 },
245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "+july", 7 },
246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "+june", 6 },
247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "+november", 11 },
248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "+october", 10 },
249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "+september", 9 },
250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "-", 0 },
251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "-august", 8 },
252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "-december", 12 },
253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "-july", 7 },
254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "-june", 6 },
255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "-november", 11 },
256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "-october", 10 },
257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "-september", 9 },
258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // The l+n branch (with its sub-nodes) is a duplicate but will be written
259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // both times because each time it follows a different linear-match node.
260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "xjuly", 7 },
261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "xjune", 6 }
262b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkData(data, LENGTHOF(data));
264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoBytesTrie *BytesTrieTest::buildMonthsTrie(UStringTrieBuildOption buildOption) {
267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // All types of nodes leading to the same value,
268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // for code coverage of recursive functions.
269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // In particular, we need a lot of branches on some single level
270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // to exercise a split-branch node.
271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "august", 8 },
273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jan", 1 },
274b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jan.", 1 },
275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jana", 1 },
276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janbb", 1 },
277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janc", 1 },
278b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janddd", 1 },
279b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janee", 1 },
280b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janef", 1 },
281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janf", 1 },
282b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jangg", 1 },
283b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janh", 1 },
284b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janiiii", 1 },
285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janj", 1 },
286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jankk", 1 },
287b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jankl", 1 },
288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jankmm", 1 },
289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janl", 1 },
290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janm", 1 },
291b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jannnnnnnnnnnnnnnnnnnnnnnnnnnnn", 1 },
292b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jano", 1 },
293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janpp", 1 },
294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janqqq", 1 },
295b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janr", 1 },
296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "januar", 1 },
297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "january", 1 },
298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "july", 7 },
299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jun", 6 },
300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jun.", 6 },
301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "june", 6 }
302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return buildTrie(data, LENGTHOF(data), buildOption);
304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestHasUniqueValue() {
307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<BytesTrie> trie(buildMonthsTrie(USTRINGTRIE_BUILD_FAST));
308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie.isNull()) {
309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;  // buildTrie() reported an error
310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t uniqueValue;
312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie->hasUniqueValue(uniqueValue)) {
313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("unique value at root");
314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('j');
316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('a');
317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('n');
318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // hasUniqueValue() directly after next()
319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(!trie->hasUniqueValue(uniqueValue) || uniqueValue!=1) {
320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("not unique value 1 after \"jan\"");
321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->first('j');
323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('u');
324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie->hasUniqueValue(uniqueValue)) {
325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("unique value after \"ju\"");
326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie->next('n')!=USTRINGTRIE_INTERMEDIATE_VALUE || 6!=trie->getValue()) {
328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("not normal value 6 after \"jun\"");
329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // hasUniqueValue() after getValue()
331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(!trie->hasUniqueValue(uniqueValue) || uniqueValue!=6) {
332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("not unique value 6 after \"jun\"");
333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // hasUniqueValue() from within a linear-match node
335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->first('a');
336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('u');
337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(!trie->hasUniqueValue(uniqueValue) || uniqueValue!=8) {
338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("not unique value 8 after \"au\"");
339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestGetNextBytes() {
343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<BytesTrie> trie(buildMonthsTrie(USTRINGTRIE_BUILD_SMALL));
344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie.isNull()) {
345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;  // buildTrie() reported an error
346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    char buffer[40];
348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    CheckedArrayByteSink sink(buffer, LENGTHOF(buffer));
349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t count=trie->getNextBytes(sink);
350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(count!=2 || sink.NumberOfBytesAppended()!=2 || buffer[0]!='a' || buffer[1]!='j') {
351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("months getNextBytes()!=[aj] at root");
352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('j');
354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('a');
355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('n');
356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // getNextBytes() directly after next()
357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    count=trie->getNextBytes(sink.Reset());
358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    buffer[count]=0;
359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(count!=20 || sink.NumberOfBytesAppended()!=20 || 0!=strcmp(buffer, ".abcdefghijklmnopqru")) {
360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("months getNextBytes()!=[.abcdefghijklmnopqru] after \"jan\"");
361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
362b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // getNextBytes() after getValue()
363b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->getValue();  // next() had returned USTRINGTRIE_INTERMEDIATE_VALUE.
364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    memset(buffer, 0, sizeof(buffer));
365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    count=trie->getNextBytes(sink.Reset());
366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(count!=20 || sink.NumberOfBytesAppended()!=20 || 0!=strcmp(buffer, ".abcdefghijklmnopqru")) {
367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("months getNextBytes()!=[.abcdefghijklmnopqru] after \"jan\"+getValue()");
368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // getNextBytes() from a linear-match node
370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('u');
371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    memset(buffer, 0, sizeof(buffer));
372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    count=trie->getNextBytes(sink.Reset());
373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(count!=1 || sink.NumberOfBytesAppended()!=1 || buffer[0]!='a') {
374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("months getNextBytes()!=[a] after \"janu\"");
375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('a');
377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    memset(buffer, 0, sizeof(buffer));
378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    count=trie->getNextBytes(sink.Reset());
379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(count!=1 || sink.NumberOfBytesAppended()!=1 || buffer[0]!='r') {
380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("months getNextBytes()!=[r] after \"janua\"");
381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('r');
383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('y');
384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // getNextBytes() after a final match
385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    count=trie->getNextBytes(sink.Reset());
386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(count!=0 || sink.NumberOfBytesAppended()!=0) {
387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("months getNextBytes()!=[] after \"january\"");
388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestIteratorFromBranch() {
392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<BytesTrie> trie(buildMonthsTrie(USTRINGTRIE_BUILD_FAST));
393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie.isNull()) {
394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;  // buildTrie() reported an error
395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Go to a branch node.
397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('j');
398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('a');
399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('n');
400b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "TestIteratorFromBranch()");
401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie::Iterator iter(*trie, 0, errorCode);
402b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(errorCode.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
403b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
405b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Expected data: Same as in buildMonthsTrie(), except only the suffixes
406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // following "jan".
407b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "", 1 },
409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { ".", 1 },
410b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "a", 1 },
411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "bb", 1 },
412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "c", 1 },
413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "ddd", 1 },
414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "ee", 1 },
415b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "ef", 1 },
416b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "f", 1 },
417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "gg", 1 },
418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "h", 1 },
419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "iiii", 1 },
420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "j", 1 },
421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "kk", 1 },
422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "kl", 1 },
423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "kmm", 1 },
424b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "l", 1 },
425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "m", 1 },
426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "nnnnnnnnnnnnnnnnnnnnnnnnnnnn", 1 },
427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "o", 1 },
428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "pp", 1 },
429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "qqq", 1 },
430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "r", 1 },
431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "uar", 1 },
432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "uary", 1 }
433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter, data, LENGTHOF(data));
435b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Reset, and we should get the same result.
436b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    logln("after iter.reset()");
437b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter.reset(), data, LENGTHOF(data));
438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
439b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
440b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestIteratorFromLinearMatch() {
441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<BytesTrie> trie(buildMonthsTrie(USTRINGTRIE_BUILD_SMALL));
442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie.isNull()) {
443b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;  // buildTrie() reported an error
444b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
445b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Go into a linear-match node.
446b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('j');
447b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('a');
448b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('n');
449b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('u');
450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('a');
451b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "TestIteratorFromLinearMatch()");
452b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie::Iterator iter(*trie, 0, errorCode);
453b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(errorCode.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
455b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
456b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Expected data: Same as in buildMonthsTrie(), except only the suffixes
457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // following "janua".
458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "r", 1 },
460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "ry", 1 }
461b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter, data, LENGTHOF(data));
463b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Reset, and we should get the same result.
464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    logln("after iter.reset()");
465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter.reset(), data, LENGTHOF(data));
466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
468b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestTruncatingIteratorFromRoot() {
469b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<BytesTrie> trie(buildMonthsTrie(USTRINGTRIE_BUILD_FAST));
470b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie.isNull()) {
471b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;  // buildTrie() reported an error
472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "TestTruncatingIteratorFromRoot()");
474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie::Iterator iter(*trie, 4, errorCode);
475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(errorCode.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Expected data: Same as in buildMonthsTrie(), except only the first 4 characters
479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // of each string, and no string duplicates from the truncation.
480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "augu", -1 },
482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jan", 1 },
483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jan.", 1 },
484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jana", 1 },
485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janb", -1 },
486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janc", 1 },
487b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jand", -1 },
488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jane", -1 },
489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janf", 1 },
490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jang", -1 },
491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janh", 1 },
492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jani", -1 },
493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janj", 1 },
494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jank", -1 },
495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janl", 1 },
496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janm", 1 },
497b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jann", -1 },
498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jano", 1 },
499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janp", -1 },
500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janq", -1 },
501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janr", 1 },
502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "janu", -1 },
503b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "july", 7 },
504b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jun", 6 },
505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "jun.", 6 },
506b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "june", 6 }
507b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
508b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter, data, LENGTHOF(data));
509b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Reset, and we should get the same result.
510b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    logln("after iter.reset()");
511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter.reset(), data, LENGTHOF(data));
512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
513b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestTruncatingIteratorFromLinearMatchShort() {
515b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcdef", 10 },
517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcdepq", 200 },
518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcdeyz", 3000 }
519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<BytesTrie> trie(buildTrie(data, LENGTHOF(data), USTRINGTRIE_BUILD_FAST));
521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie.isNull()) {
522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;  // buildTrie() reported an error
523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Go into a linear-match node.
525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('a');
526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('b');
527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "TestTruncatingIteratorFromLinearMatchShort()");
528b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Truncate within the linear-match node.
529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie::Iterator iter(*trie, 2, errorCode);
530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(errorCode.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
531b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue expected[]={
534b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "cd", -1 }
535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter, expected, LENGTHOF(expected));
537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Reset, and we should get the same result.
538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    logln("after iter.reset()");
539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter.reset(), expected, LENGTHOF(expected));
540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestTruncatingIteratorFromLinearMatchLong() {
543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcdef", 10 },
545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcdepq", 200 },
546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "abcdeyz", 3000 }
547b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
548b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<BytesTrie> trie(buildTrie(data, LENGTHOF(data), USTRINGTRIE_BUILD_FAST));
549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie.isNull()) {
550b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;  // buildTrie() reported an error
551b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Go into a linear-match node.
553b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('a');
554b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('b');
555b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie->next('c');
556b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "TestTruncatingIteratorFromLinearMatchLong()");
557b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Truncate after the linear-match node.
558b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie::Iterator iter(*trie, 3, errorCode);
559b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(errorCode.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
560b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
561b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue expected[]={
563b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "def", 10 },
564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "dep", -1 },
565b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "dey", -1 }
566b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
567b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter, expected, LENGTHOF(expected));
568b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Reset, and we should get the same result.
569b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    logln("after iter.reset()");
570b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter.reset(), expected, LENGTHOF(expected));
571b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
572b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
573b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::TestIteratorFromBytes() {
574b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static const StringAndValue data[]={
575b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "mm", 3 },
576b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "mmm", 33 },
577b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        { "mmnop", 333 }
578b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
579b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    builder_->clear();
580b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "TestIteratorFromBytes()");
581b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=0; i<LENGTHOF(data); ++i) {
582b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        builder_->add(data[i].s, data[i].value, errorCode);
583b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
584b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    StringPiece trieBytes=builder_->buildStringPiece(USTRINGTRIE_BUILD_FAST, errorCode);
585b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie::Iterator iter(trieBytes.data(), 0, errorCode);
586b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter, data, LENGTHOF(data));
587b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
588b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
589b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::checkData(const StringAndValue data[], int32_t dataLength) {
590b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    logln("checkData(dataLength=%d, fast)", (int)dataLength);
591b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkData(data, dataLength, USTRINGTRIE_BUILD_FAST);
592b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    logln("checkData(dataLength=%d, small)", (int)dataLength);
593b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkData(data, dataLength, USTRINGTRIE_BUILD_SMALL);
594b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
595b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
596b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::checkData(const StringAndValue data[], int32_t dataLength, UStringTrieBuildOption buildOption) {
597b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<BytesTrie> trie(buildTrie(data, dataLength, buildOption));
598b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(trie.isNull()) {
599b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;  // buildTrie() reported an error
600b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
601b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkFirst(*trie, data, dataLength);
602b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkNext(*trie, data, dataLength);
603b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkNextWithState(*trie, data, dataLength);
604b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkNextString(*trie, data, dataLength);
605b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(*trie, data, dataLength);
606b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
607b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
608b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoBytesTrie *BytesTrieTest::buildTrie(const StringAndValue data[], int32_t dataLength,
609b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                    UStringTrieBuildOption buildOption) {
610b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "buildTrie()");
611b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Add the items to the trie builder in an interesting (not trivial, not random) order.
612b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t index, step;
613b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(dataLength&1) {
614b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Odd number of items.
615b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=dataLength/2;
616b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        step=2;
617b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if((dataLength%3)!=0) {
618b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Not a multiple of 3.
619b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=dataLength/5;
620b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        step=3;
621b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
622b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=dataLength-1;
623b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        step=-1;
624b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
625b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    builder_->clear();
626b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=0; i<dataLength; ++i) {
627b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        builder_->add(data[index].s, data[index].value, errorCode);
628b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=(index+step)%dataLength;
629b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
630b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    StringPiece sp=builder_->buildStringPiece(buildOption, errorCode);
631b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<BytesTrie> trie(builder_->build(buildOption, errorCode));
632b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(!errorCode.logIfFailureAndReset("add()/build()")) {
633b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        builder_->add("zzz", 999, errorCode);
634b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(errorCode.reset()!=U_NO_WRITE_PERMISSION) {
635b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("builder.build().add(zzz) did not set U_NO_WRITE_PERMISSION");
636b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
637b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
638b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    logln("serialized trie size: %ld bytes\n", (long)sp.length());
639b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    StringPiece sp2=builder_->buildStringPiece(buildOption, errorCode);
640b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(sp.data()==sp2.data()) {
641b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("builder.buildStringPiece() before & after build() returned same array");
642b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
643b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(errorCode.isFailure()) {
644b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
645b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
646b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Tries from either build() method should be identical but
647b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // BytesTrie does not implement equals().
648b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // We just return either one.
649b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if((dataLength&1)!=0) {
650b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return trie.orphan();
651b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
652b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return new BytesTrie(sp2.data());
653b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
654b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
655b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
656b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::checkFirst(BytesTrie &trie,
657b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                               const StringAndValue data[], int32_t dataLength) {
658b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=0; i<dataLength; ++i) {
659b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int c=*data[i].s;
660b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(c==0) {
661b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            continue;  // skip empty string
662b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
663b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UStringTrieResult firstResult=trie.first(c);
664b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t firstValue=USTRINGTRIE_HAS_VALUE(firstResult) ? trie.getValue() : -1;
665b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UStringTrieResult nextResult=trie.next(data[i].s[1]);
666b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(firstResult!=trie.reset().next(c) ||
667b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho           firstResult!=trie.current() ||
668b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho           firstValue!=(USTRINGTRIE_HAS_VALUE(firstResult) ? trie.getValue() : -1) ||
669b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho           nextResult!=trie.next(data[i].s[1])
670b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ) {
671b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie.first(%c)!=trie.reset().next(same) for %s",
672b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  c, data[i].s);
673b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
674b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
675b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    trie.reset();
676b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
677b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
678b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::checkNext(BytesTrie &trie,
679b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                              const StringAndValue data[], int32_t dataLength) {
680b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie::State state;
681b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=0; i<dataLength; ++i) {
682b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t stringLength= (i&1) ? -1 : strlen(data[i].s);
683b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UStringTrieResult result;
684b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if( !USTRINGTRIE_HAS_VALUE(result=trie.next(data[i].s, stringLength)) ||
685b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result!=trie.current()
686b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ) {
687b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie does not seem to contain %s", data[i].s);
688b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(trie.getValue()!=data[i].value) {
689b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie value for %s is %ld=0x%lx instead of expected %ld=0x%lx",
690b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  data[i].s,
691b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  (long)trie.getValue(), (long)trie.getValue(),
692b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  (long)data[i].value, (long)data[i].value);
693b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(result!=trie.current() || trie.getValue()!=data[i].value) {
694b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie value for %s changes when repeating current()/getValue()", data[i].s);
695b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
696b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        trie.reset();
697b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        stringLength=strlen(data[i].s);
698b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        result=trie.current();
699b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for(int32_t j=0; j<stringLength; ++j) {
700b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(!USTRINGTRIE_HAS_NEXT(result)) {
701b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errln("trie.current()!=hasNext before end of %s (at index %d)", data[i].s, j);
702b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
703b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
704b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(result==USTRINGTRIE_INTERMEDIATE_VALUE) {
705b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                trie.getValue();
706b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if(trie.current()!=USTRINGTRIE_INTERMEDIATE_VALUE) {
707b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errln("trie.getValue().current()!=USTRINGTRIE_INTERMEDIATE_VALUE before end of %s (at index %d)", data[i].s, j);
708b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
709b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
710b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
711b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result=trie.next(data[i].s[j]);
712b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(!USTRINGTRIE_MATCHES(result)) {
713b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errln("trie.next()=USTRINGTRIE_NO_MATCH before end of %s (at index %d)", data[i].s, j);
714b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
715b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
716b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(result!=trie.current()) {
717b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errln("trie.next()!=following current() before end of %s (at index %d)", data[i].s, j);
718b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
719b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
720b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(!USTRINGTRIE_HAS_VALUE(result)) {
722b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie.next()!=hasValue at the end of %s", data[i].s);
723b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            continue;
724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
725b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        trie.getValue();
726b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(result!=trie.current()) {
727b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie.current() != current()+getValue()+current() after end of %s",
728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  data[i].s);
729b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
730b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Compare the final current() with whether next() can actually continue.
731b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        trie.saveState(state);
732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UBool nextContinues=FALSE;
733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Try all graphic characters; we only use those in test strings in this file.
734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#if U_CHARSET_FAMILY==U_ASCII_FAMILY
735b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const int32_t minChar=0x20;
736b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const int32_t maxChar=0x7e;
737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY
738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const int32_t minChar=0x40;
739b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const int32_t maxChar=0xfe;
740b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#else
741b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const int32_t minChar=0;
742b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const int32_t maxChar=0xff;
743b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#endif
744b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for(int32_t c=minChar; c<=maxChar; ++c) {
745b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(trie.resetToState(state).next(c)) {
746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                nextContinues=TRUE;
747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if((result==USTRINGTRIE_INTERMEDIATE_VALUE)!=nextContinues) {
751b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("(trie.current()==USTRINGTRIE_INTERMEDIATE_VALUE) contradicts "
752b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  "(trie.next(some byte)!=USTRINGTRIE_NO_MATCH) after end of %s", data[i].s);
753b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
754b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        trie.reset();
755b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
756b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
757b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
758b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::checkNextWithState(BytesTrie &trie,
759b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                       const StringAndValue data[], int32_t dataLength) {
760b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie::State noState, state;
761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=0; i<dataLength; ++i) {
762b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if((i&1)==0) {
763b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // This should have no effect.
764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            trie.resetToState(noState);
765b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const char *expectedString=data[i].s;
767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t stringLength=strlen(expectedString);
768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t partialLength=stringLength/3;
769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for(int32_t j=0; j<partialLength; ++j) {
770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(!USTRINGTRIE_MATCHES(trie.next(expectedString[j]))) {
771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errln("trie.next()=USTRINGTRIE_NO_MATCH for a prefix of %s", data[i].s);
772b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        trie.saveState(state);
776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UStringTrieResult resultAtState=trie.current();
777b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UStringTrieResult result;
778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t valueAtState=-99;
779b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(USTRINGTRIE_HAS_VALUE(resultAtState)) {
780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            valueAtState=trie.getValue();
781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        result=trie.next(0);  // mismatch
783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(result!=USTRINGTRIE_NO_MATCH || result!=trie.current()) {
784b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie.next(0) matched after part of %s", data[i].s);
785b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if( resultAtState!=trie.resetToState(state).current() ||
787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            (USTRINGTRIE_HAS_VALUE(resultAtState) && valueAtState!=trie.getValue())
788b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ) {
789b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie.next(part of %s) changes current()/getValue() after "
790b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  "saveState/next(0)/resetToState",
791b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  data[i].s);
792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(!USTRINGTRIE_HAS_VALUE(
793b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                      result=trie.next(expectedString+partialLength,
794b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                       stringLength-partialLength)) ||
795b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  result!=trie.current()) {
796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie.next(rest of %s) does not seem to contain %s after "
797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  "saveState/next(0)/resetToState",
798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  data[i].s, data[i].s);
799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(!USTRINGTRIE_HAS_VALUE(
800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                      result=trie.resetToState(state).
801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                  next(expectedString+partialLength,
802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                       stringLength-partialLength)) ||
803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  result!=trie.current()) {
804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie does not seem to contain %s after saveState/next(rest)/resetToState",
805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  data[i].s);
806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(trie.getValue()!=data[i].value) {
807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie value for %s is %ld=0x%lx instead of expected %ld=0x%lx",
808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  data[i].s,
809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  (long)trie.getValue(), (long)trie.getValue(),
810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  (long)data[i].value, (long)data[i].value);
811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        trie.reset();
813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
815b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// next(string) is also tested in other functions,
817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// but here we try to go partway through the string, and then beyond it.
818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::checkNextString(BytesTrie &trie,
819b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                    const StringAndValue data[], int32_t dataLength) {
820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=0; i<dataLength; ++i) {
821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const char *expectedString=data[i].s;
822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t stringLength=strlen(expectedString);
823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(!trie.next(expectedString, stringLength/2)) {
824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie.next(up to middle of string)=USTRINGTRIE_NO_MATCH for %s", data[i].s);
825b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            continue;
826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Test that we stop properly at the end of the string.
828b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(trie.next(expectedString+stringLength/2, stringLength+1-stringLength/2)) {
829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie.next(string+NUL)!=USTRINGTRIE_NO_MATCH for %s", data[i].s);
830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        trie.reset();
832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::checkIterator(const BytesTrie &trie,
836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                  const StringAndValue data[], int32_t dataLength) {
837b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "checkIterator()");
838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    BytesTrie::Iterator iter(trie, 0, errorCode);
839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(errorCode.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
840b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
841b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
842b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    checkIterator(iter, data, dataLength);
843b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
844b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
845b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid BytesTrieTest::checkIterator(BytesTrie::Iterator &iter,
846b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                  const StringAndValue data[], int32_t dataLength) {
847b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IcuTestErrorCode errorCode(*this, "checkIterator()");
848b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=0; i<dataLength; ++i) {
849b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(!iter.hasNext()) {
850b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie iterator hasNext()=FALSE for item %d: %s", (int)i, data[i].s);
851b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
852b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
853b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UBool hasNext=iter.next(errorCode);
854b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(errorCode.logIfFailureAndReset("trie iterator next() for item %d: %s", (int)i, data[i].s)) {
855b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
856b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
857b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(!hasNext) {
858b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie iterator next()=FALSE for item %d: %s", (int)i, data[i].s);
859b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
860b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
861b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(iter.getString()!=StringPiece(data[i].s)) {
862b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie iterator next().getString()=%s but expected %s for item %d",
863b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  iter.getString().data(), data[i].s, (int)i);
864b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
865b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(iter.getValue()!=data[i].value) {
866b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("trie iterator next().getValue()=%ld=0x%lx but expected %ld=0x%lx for item %d: %s",
867b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  (long)iter.getValue(), (long)iter.getValue(),
868b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  (long)data[i].value, (long)data[i].value,
869b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  (int)i, data[i].s);
870b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
871b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
872b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(iter.hasNext()) {
873b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("trie iterator hasNext()=TRUE after all items");
874b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
875b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool hasNext=iter.next(errorCode);
876b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    errorCode.logIfFailureAndReset("trie iterator next() after all items");
877b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(hasNext) {
878b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("trie iterator next()=TRUE after all items");
879b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
880b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
881