2 *******************************************************************************
3 * Copyright (C) 2010-2014, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 *******************************************************************************
6 * file name: bytetrietest.cpp
8 * tab size: 8 (not used)
11 * created on: 2010nov16
12 * created by: Markus W. Scherer
17 #include "unicode/utypes.h"
18 #include "unicode/bytestrie.h"
19 #include "unicode/bytestriebuilder.h"
20 #include "unicode/localpointer.h"
21 #include "unicode/stringpiece.h"
25 struct StringAndValue
{
30 class BytesTrieTest
: public IntlTest
{
33 virtual ~BytesTrieTest();
35 void runIndexedTest(int32_t index
, UBool exec
, const char *&name
, char *par
=NULL
);
40 void TestShortestBranch();
42 void TestLongSequence();
43 void TestLongBranch();
44 void TestValuesForState();
47 BytesTrie
*buildMonthsTrie(UStringTrieBuildOption buildOption
);
48 void TestHasUniqueValue();
49 void TestGetNextBytes();
50 void TestIteratorFromBranch();
51 void TestIteratorFromLinearMatch();
52 void TestTruncatingIteratorFromRoot();
53 void TestTruncatingIteratorFromLinearMatchShort();
54 void TestTruncatingIteratorFromLinearMatchLong();
55 void TestIteratorFromBytes();
57 void checkData(const StringAndValue data
[], int32_t dataLength
);
58 void checkData(const StringAndValue data
[], int32_t dataLength
, UStringTrieBuildOption buildOption
);
59 BytesTrie
*buildTrie(const StringAndValue data
[], int32_t dataLength
,
60 UStringTrieBuildOption buildOption
);
61 void checkFirst(BytesTrie
&trie
, const StringAndValue data
[], int32_t dataLength
);
62 void checkNext(BytesTrie
&trie
, const StringAndValue data
[], int32_t dataLength
);
63 void checkNextWithState(BytesTrie
&trie
, const StringAndValue data
[], int32_t dataLength
);
64 void checkNextString(BytesTrie
&trie
, const StringAndValue data
[], int32_t dataLength
);
65 void checkIterator(const BytesTrie
&trie
, const StringAndValue data
[], int32_t dataLength
);
66 void checkIterator(BytesTrie::Iterator
&iter
, const StringAndValue data
[], int32_t dataLength
);
69 BytesTrieBuilder
*builder_
;
72 extern IntlTest
*createBytesTrieTest() {
73 return new BytesTrieTest();
76 BytesTrieTest::BytesTrieTest() : builder_(NULL
) {
77 IcuTestErrorCode
errorCode(*this, "BytesTrieTest()");
78 builder_
=new BytesTrieBuilder(errorCode
);
81 BytesTrieTest::~BytesTrieTest() {
85 void BytesTrieTest::runIndexedTest(int32_t index
, UBool exec
, const char *&name
, char * /*par*/) {
87 logln("TestSuite BytesTrieTest: ");
90 TESTCASE_AUTO(TestBuilder
);
91 TESTCASE_AUTO(TestEmpty
);
92 TESTCASE_AUTO(Test_a
);
93 TESTCASE_AUTO(Test_a_ab
);
94 TESTCASE_AUTO(TestShortestBranch
);
95 TESTCASE_AUTO(TestBranches
);
96 TESTCASE_AUTO(TestLongSequence
);
97 TESTCASE_AUTO(TestLongBranch
);
98 TESTCASE_AUTO(TestValuesForState
);
99 TESTCASE_AUTO(TestCompact
);
100 TESTCASE_AUTO(TestHasUniqueValue
);
101 TESTCASE_AUTO(TestGetNextBytes
);
102 TESTCASE_AUTO(TestIteratorFromBranch
);
103 TESTCASE_AUTO(TestIteratorFromLinearMatch
);
104 TESTCASE_AUTO(TestTruncatingIteratorFromRoot
);
105 TESTCASE_AUTO(TestTruncatingIteratorFromLinearMatchShort
);
106 TESTCASE_AUTO(TestTruncatingIteratorFromLinearMatchLong
);
107 TESTCASE_AUTO(TestIteratorFromBytes
);
111 void BytesTrieTest::TestBuilder() {
112 IcuTestErrorCode
errorCode(*this, "TestBuilder()");
114 delete builder_
->build(USTRINGTRIE_BUILD_FAST
, errorCode
);
115 if(errorCode
.reset()!=U_INDEX_OUTOFBOUNDS_ERROR
) {
116 errln("BytesTrieBuilder().build() did not set U_INDEX_OUTOFBOUNDS_ERROR");
119 // TODO: remove .build(...) once add() checks for duplicates.
120 builder_
->add("=", 0, errorCode
).add("=", 1, errorCode
).build(USTRINGTRIE_BUILD_FAST
, errorCode
);
121 if(errorCode
.reset()!=U_ILLEGAL_ARGUMENT_ERROR
) {
122 errln("BytesTrieBuilder.add() did not detect duplicates");
127 void BytesTrieTest::TestEmpty() {
128 static const StringAndValue data
[]={
131 checkData(data
, UPRV_LENGTHOF(data
));
134 void BytesTrieTest::Test_a() {
135 static const StringAndValue data
[]={
138 checkData(data
, UPRV_LENGTHOF(data
));
141 void BytesTrieTest::Test_a_ab() {
142 static const StringAndValue data
[]={
146 checkData(data
, UPRV_LENGTHOF(data
));
149 void BytesTrieTest::TestShortestBranch() {
150 static const StringAndValue data
[]={
154 checkData(data
, UPRV_LENGTHOF(data
));
157 void BytesTrieTest::TestBranches() {
158 static const StringAndValue data
[]={
166 { "ppppp", 0x40000 },
171 { "vv", 0x7fffffff },
172 { "zz", (int32_t)0x80000000 }
174 for(int32_t length
=2; length
<=UPRV_LENGTHOF(data
); ++length
) {
175 logln("TestBranches length=%d", (int)length
);
176 checkData(data
, length
);
180 void BytesTrieTest::TestLongSequence() {
181 static const StringAndValue data
[]={
183 // sequence of linear-match nodes
184 { "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", -2 },
185 // more than 256 bytes
186 { "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
187 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
188 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
189 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
190 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
191 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", -3 }
193 checkData(data
, UPRV_LENGTHOF(data
));
196 void BytesTrieTest::TestLongBranch() {
197 // Split-branch and interesting compact-integer values.
198 static const StringAndValue data
[]={
211 { "l234567890", 0x1b00 },
212 { "l234567890123", 0x1b01 },
213 { "nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", 0x10ffff },
214 { "oooooooooooooooooooooooooooooooooooooooooooooooooooooo", 0x110000 },
215 { "pppppppppppppppppppppppppppppppppppppppppppppppppppppp", 0x120000 },
217 { "s2345", 0x4444444 },
218 { "t234567890", 0x77777777 },
219 { "z", (int32_t)0x80000001 }
221 checkData(data
, UPRV_LENGTHOF(data
));
224 void BytesTrieTest::TestValuesForState() {
225 // Check that saveState() and resetToState() interact properly
226 // with next() and current().
227 static const StringAndValue data
[]={
235 checkData(data
, UPRV_LENGTHOF(data
));
238 void BytesTrieTest::TestCompact() {
239 // Duplicate trailing strings and values provide opportunities for compacting.
240 static const StringAndValue data
[]={
257 // The l+n branch (with its sub-nodes) is a duplicate but will be written
258 // both times because each time it follows a different linear-match node.
262 checkData(data
, UPRV_LENGTHOF(data
));
265 BytesTrie
*BytesTrieTest::buildMonthsTrie(UStringTrieBuildOption buildOption
) {
266 // All types of nodes leading to the same value,
267 // for code coverage of recursive functions.
268 // In particular, we need a lot of branches on some single level
269 // to exercise a split-branch node.
270 static const StringAndValue data
[]={
290 { "jannnnnnnnnnnnnnnnnnnnnnnnnnnnn", 1 },
302 return buildTrie(data
, UPRV_LENGTHOF(data
), buildOption
);
305 void BytesTrieTest::TestHasUniqueValue() {
306 LocalPointer
<BytesTrie
> trie(buildMonthsTrie(USTRINGTRIE_BUILD_FAST
));
308 return; // buildTrie() reported an error
311 if(trie
->hasUniqueValue(uniqueValue
)) {
312 errln("unique value at root");
317 // hasUniqueValue() directly after next()
318 if(!trie
->hasUniqueValue(uniqueValue
) || uniqueValue
!=1) {
319 errln("not unique value 1 after \"jan\"");
323 if(trie
->hasUniqueValue(uniqueValue
)) {
324 errln("unique value after \"ju\"");
326 if(trie
->next('n')!=USTRINGTRIE_INTERMEDIATE_VALUE
|| 6!=trie
->getValue()) {
327 errln("not normal value 6 after \"jun\"");
329 // hasUniqueValue() after getValue()
330 if(!trie
->hasUniqueValue(uniqueValue
) || uniqueValue
!=6) {
331 errln("not unique value 6 after \"jun\"");
333 // hasUniqueValue() from within a linear-match node
336 if(!trie
->hasUniqueValue(uniqueValue
) || uniqueValue
!=8) {
337 errln("not unique value 8 after \"au\"");
341 void BytesTrieTest::TestGetNextBytes() {
342 LocalPointer
<BytesTrie
> trie(buildMonthsTrie(USTRINGTRIE_BUILD_SMALL
));
344 return; // buildTrie() reported an error
347 CheckedArrayByteSink
sink(buffer
, UPRV_LENGTHOF(buffer
));
348 int32_t count
=trie
->getNextBytes(sink
);
349 if(count
!=2 || sink
.NumberOfBytesAppended()!=2 || buffer
[0]!='a' || buffer
[1]!='j') {
350 errln("months getNextBytes()!=[aj] at root");
355 // getNextBytes() directly after next()
356 count
=trie
->getNextBytes(sink
.Reset());
358 if(count
!=20 || sink
.NumberOfBytesAppended()!=20 || 0!=strcmp(buffer
, ".abcdefghijklmnopqru")) {
359 errln("months getNextBytes()!=[.abcdefghijklmnopqru] after \"jan\"");
361 // getNextBytes() after getValue()
362 trie
->getValue(); // next() had returned USTRINGTRIE_INTERMEDIATE_VALUE.
363 memset(buffer
, 0, sizeof(buffer
));
364 count
=trie
->getNextBytes(sink
.Reset());
365 if(count
!=20 || sink
.NumberOfBytesAppended()!=20 || 0!=strcmp(buffer
, ".abcdefghijklmnopqru")) {
366 errln("months getNextBytes()!=[.abcdefghijklmnopqru] after \"jan\"+getValue()");
368 // getNextBytes() from a linear-match node
370 memset(buffer
, 0, sizeof(buffer
));
371 count
=trie
->getNextBytes(sink
.Reset());
372 if(count
!=1 || sink
.NumberOfBytesAppended()!=1 || buffer
[0]!='a') {
373 errln("months getNextBytes()!=[a] after \"janu\"");
376 memset(buffer
, 0, sizeof(buffer
));
377 count
=trie
->getNextBytes(sink
.Reset());
378 if(count
!=1 || sink
.NumberOfBytesAppended()!=1 || buffer
[0]!='r') {
379 errln("months getNextBytes()!=[r] after \"janua\"");
383 // getNextBytes() after a final match
384 count
=trie
->getNextBytes(sink
.Reset());
385 if(count
!=0 || sink
.NumberOfBytesAppended()!=0) {
386 errln("months getNextBytes()!=[] after \"january\"");
390 void BytesTrieTest::TestIteratorFromBranch() {
391 LocalPointer
<BytesTrie
> trie(buildMonthsTrie(USTRINGTRIE_BUILD_FAST
));
393 return; // buildTrie() reported an error
395 // Go to a branch node.
399 IcuTestErrorCode
errorCode(*this, "TestIteratorFromBranch()");
400 BytesTrie::Iterator
iter(*trie
, 0, errorCode
);
401 if(errorCode
.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
404 // Expected data: Same as in buildMonthsTrie(), except only the suffixes
406 static const StringAndValue data
[]={
425 { "nnnnnnnnnnnnnnnnnnnnnnnnnnnn", 1 },
433 checkIterator(iter
, data
, UPRV_LENGTHOF(data
));
434 // Reset, and we should get the same result.
435 logln("after iter.reset()");
436 checkIterator(iter
.reset(), data
, UPRV_LENGTHOF(data
));
439 void BytesTrieTest::TestIteratorFromLinearMatch() {
440 LocalPointer
<BytesTrie
> trie(buildMonthsTrie(USTRINGTRIE_BUILD_SMALL
));
442 return; // buildTrie() reported an error
444 // Go into a linear-match node.
450 IcuTestErrorCode
errorCode(*this, "TestIteratorFromLinearMatch()");
451 BytesTrie::Iterator
iter(*trie
, 0, errorCode
);
452 if(errorCode
.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
455 // Expected data: Same as in buildMonthsTrie(), except only the suffixes
456 // following "janua".
457 static const StringAndValue data
[]={
461 checkIterator(iter
, data
, UPRV_LENGTHOF(data
));
462 // Reset, and we should get the same result.
463 logln("after iter.reset()");
464 checkIterator(iter
.reset(), data
, UPRV_LENGTHOF(data
));
467 void BytesTrieTest::TestTruncatingIteratorFromRoot() {
468 LocalPointer
<BytesTrie
> trie(buildMonthsTrie(USTRINGTRIE_BUILD_FAST
));
470 return; // buildTrie() reported an error
472 IcuTestErrorCode
errorCode(*this, "TestTruncatingIteratorFromRoot()");
473 BytesTrie::Iterator
iter(*trie
, 4, errorCode
);
474 if(errorCode
.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
477 // Expected data: Same as in buildMonthsTrie(), except only the first 4 characters
478 // of each string, and no string duplicates from the truncation.
479 static const StringAndValue data
[]={
507 checkIterator(iter
, data
, UPRV_LENGTHOF(data
));
508 // Reset, and we should get the same result.
509 logln("after iter.reset()");
510 checkIterator(iter
.reset(), data
, UPRV_LENGTHOF(data
));
513 void BytesTrieTest::TestTruncatingIteratorFromLinearMatchShort() {
514 static const StringAndValue data
[]={
519 LocalPointer
<BytesTrie
> trie(buildTrie(data
, UPRV_LENGTHOF(data
), USTRINGTRIE_BUILD_FAST
));
521 return; // buildTrie() reported an error
523 // Go into a linear-match node.
526 IcuTestErrorCode
errorCode(*this, "TestTruncatingIteratorFromLinearMatchShort()");
527 // Truncate within the linear-match node.
528 BytesTrie::Iterator
iter(*trie
, 2, errorCode
);
529 if(errorCode
.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
532 static const StringAndValue expected
[]={
535 checkIterator(iter
, expected
, UPRV_LENGTHOF(expected
));
536 // Reset, and we should get the same result.
537 logln("after iter.reset()");
538 checkIterator(iter
.reset(), expected
, UPRV_LENGTHOF(expected
));
541 void BytesTrieTest::TestTruncatingIteratorFromLinearMatchLong() {
542 static const StringAndValue data
[]={
547 LocalPointer
<BytesTrie
> trie(buildTrie(data
, UPRV_LENGTHOF(data
), USTRINGTRIE_BUILD_FAST
));
549 return; // buildTrie() reported an error
551 // Go into a linear-match node.
555 IcuTestErrorCode
errorCode(*this, "TestTruncatingIteratorFromLinearMatchLong()");
556 // Truncate after the linear-match node.
557 BytesTrie::Iterator
iter(*trie
, 3, errorCode
);
558 if(errorCode
.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
561 static const StringAndValue expected
[]={
566 checkIterator(iter
, expected
, UPRV_LENGTHOF(expected
));
567 // Reset, and we should get the same result.
568 logln("after iter.reset()");
569 checkIterator(iter
.reset(), expected
, UPRV_LENGTHOF(expected
));
572 void BytesTrieTest::TestIteratorFromBytes() {
573 static const StringAndValue data
[]={
579 IcuTestErrorCode
errorCode(*this, "TestIteratorFromBytes()");
580 for(int32_t i
=0; i
<UPRV_LENGTHOF(data
); ++i
) {
581 builder_
->add(data
[i
].s
, data
[i
].value
, errorCode
);
583 StringPiece trieBytes
=builder_
->buildStringPiece(USTRINGTRIE_BUILD_FAST
, errorCode
);
584 BytesTrie::Iterator
iter(trieBytes
.data(), 0, errorCode
);
585 checkIterator(iter
, data
, UPRV_LENGTHOF(data
));
588 void BytesTrieTest::checkData(const StringAndValue data
[], int32_t dataLength
) {
589 logln("checkData(dataLength=%d, fast)", (int)dataLength
);
590 checkData(data
, dataLength
, USTRINGTRIE_BUILD_FAST
);
591 logln("checkData(dataLength=%d, small)", (int)dataLength
);
592 checkData(data
, dataLength
, USTRINGTRIE_BUILD_SMALL
);
595 void BytesTrieTest::checkData(const StringAndValue data
[], int32_t dataLength
, UStringTrieBuildOption buildOption
) {
596 LocalPointer
<BytesTrie
> trie(buildTrie(data
, dataLength
, buildOption
));
598 return; // buildTrie() reported an error
600 checkFirst(*trie
, data
, dataLength
);
601 checkNext(*trie
, data
, dataLength
);
602 checkNextWithState(*trie
, data
, dataLength
);
603 checkNextString(*trie
, data
, dataLength
);
604 checkIterator(*trie
, data
, dataLength
);
607 BytesTrie
*BytesTrieTest::buildTrie(const StringAndValue data
[], int32_t dataLength
,
608 UStringTrieBuildOption buildOption
) {
609 IcuTestErrorCode
errorCode(*this, "buildTrie()");
610 // Add the items to the trie builder in an interesting (not trivial, not random) order.
613 // Odd number of items.
616 } else if((dataLength%3
)!=0) {
617 // Not a multiple of 3.
625 for(int32_t i
=0; i
<dataLength
; ++i
) {
626 builder_
->add(data
[index
].s
, data
[index
].value
, errorCode
);
627 index
=(index
+step
)%dataLength
;
629 StringPiece sp
=builder_
->buildStringPiece(buildOption
, errorCode
);
630 LocalPointer
<BytesTrie
> trie(builder_
->build(buildOption
, errorCode
));
631 if(!errorCode
.logIfFailureAndReset("add()/build()")) {
632 builder_
->add("zzz", 999, errorCode
);
633 if(errorCode
.reset()!=U_NO_WRITE_PERMISSION
) {
634 errln("builder.build().add(zzz) did not set U_NO_WRITE_PERMISSION");
637 logln("serialized trie size: %ld bytes\n", (long)sp
.length());
638 StringPiece sp2
=builder_
->buildStringPiece(buildOption
, errorCode
);
639 if(sp
.data()==sp2
.data()) {
640 errln("builder.buildStringPiece() before & after build() returned same array");
642 if(errorCode
.isFailure()) {
645 // Tries from either build() method should be identical but
646 // BytesTrie does not implement equals().
647 // We just return either one.
648 if((dataLength
&1)!=0) {
649 return trie
.orphan();
651 return new BytesTrie(sp2
.data());
655 void BytesTrieTest::checkFirst(BytesTrie
&trie
,
656 const StringAndValue data
[], int32_t dataLength
) {
657 for(int32_t i
=0; i
<dataLength
; ++i
) {
660 continue; // skip empty string
662 UStringTrieResult firstResult
=trie
.first(c
);
663 int32_t firstValue
=USTRINGTRIE_HAS_VALUE(firstResult
) ? trie
.getValue() : -1;
664 UStringTrieResult nextResult
=trie
.next(data
[i
].s
[1]);
665 if(firstResult
!=trie
.reset().next(c
) ||
666 firstResult
!=trie
.current() ||
667 firstValue
!=(USTRINGTRIE_HAS_VALUE(firstResult
) ? trie
.getValue() : -1) ||
668 nextResult
!=trie
.next(data
[i
].s
[1])
670 errln("trie.first(%c)!=trie.reset().next(same) for %s",
677 void BytesTrieTest::checkNext(BytesTrie
&trie
,
678 const StringAndValue data
[], int32_t dataLength
) {
679 BytesTrie::State state
;
680 for(int32_t i
=0; i
<dataLength
; ++i
) {
681 int32_t stringLength
= (i
&1) ? -1 : strlen(data
[i
].s
);
682 UStringTrieResult result
;
683 if( !USTRINGTRIE_HAS_VALUE(result
=trie
.next(data
[i
].s
, stringLength
)) ||
684 result
!=trie
.current()
686 errln("trie does not seem to contain %s", data
[i
].s
);
687 } else if(trie
.getValue()!=data
[i
].value
) {
688 errln("trie value for %s is %ld=0x%lx instead of expected %ld=0x%lx",
690 (long)trie
.getValue(), (long)trie
.getValue(),
691 (long)data
[i
].value
, (long)data
[i
].value
);
692 } else if(result
!=trie
.current() || trie
.getValue()!=data
[i
].value
) {
693 errln("trie value for %s changes when repeating current()/getValue()", data
[i
].s
);
696 stringLength
=strlen(data
[i
].s
);
697 result
=trie
.current();
698 for(int32_t j
=0; j
<stringLength
; ++j
) {
699 if(!USTRINGTRIE_HAS_NEXT(result
)) {
700 errln("trie.current()!=hasNext before end of %s (at index %d)", data
[i
].s
, j
);
703 if(result
==USTRINGTRIE_INTERMEDIATE_VALUE
) {
705 if(trie
.current()!=USTRINGTRIE_INTERMEDIATE_VALUE
) {
706 errln("trie.getValue().current()!=USTRINGTRIE_INTERMEDIATE_VALUE before end of %s (at index %d)", data
[i
].s
, j
);
710 result
=trie
.next(data
[i
].s
[j
]);
711 if(!USTRINGTRIE_MATCHES(result
)) {
712 errln("trie.next()=USTRINGTRIE_NO_MATCH before end of %s (at index %d)", data
[i
].s
, j
);
715 if(result
!=trie
.current()) {
716 errln("trie.next()!=following current() before end of %s (at index %d)", data
[i
].s
, j
);
720 if(!USTRINGTRIE_HAS_VALUE(result
)) {
721 errln("trie.next()!=hasValue at the end of %s", data
[i
].s
);
725 if(result
!=trie
.current()) {
726 errln("trie.current() != current()+getValue()+current() after end of %s",
729 // Compare the final current() with whether next() can actually continue.
730 trie
.saveState(state
);
731 UBool nextContinues
=FALSE
;
732 // Try all graphic characters; we only use those in test strings in this file.
733 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
734 const int32_t minChar
=0x20;
735 const int32_t maxChar
=0x7e;
736 #elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY
737 const int32_t minChar
=0x40;
738 const int32_t maxChar
=0xfe;
740 const int32_t minChar
=0;
741 const int32_t maxChar
=0xff;
743 for(int32_t c
=minChar
; c
<=maxChar
; ++c
) {
744 if(trie
.resetToState(state
).next(c
)) {
749 if((result
==USTRINGTRIE_INTERMEDIATE_VALUE
)!=nextContinues
) {
750 errln("(trie.current()==USTRINGTRIE_INTERMEDIATE_VALUE) contradicts "
751 "(trie.next(some byte)!=USTRINGTRIE_NO_MATCH) after end of %s", data
[i
].s
);
757 void BytesTrieTest::checkNextWithState(BytesTrie
&trie
,
758 const StringAndValue data
[], int32_t dataLength
) {
759 BytesTrie::State noState
, state
;
760 for(int32_t i
=0; i
<dataLength
; ++i
) {
762 // This should have no effect.
763 trie
.resetToState(noState
);
765 const char *expectedString
=data
[i
].s
;
766 int32_t stringLength
=strlen(expectedString
);
767 int32_t partialLength
=stringLength
/3;
768 for(int32_t j
=0; j
<partialLength
; ++j
) {
769 if(!USTRINGTRIE_MATCHES(trie
.next(expectedString
[j
]))) {
770 errln("trie.next()=USTRINGTRIE_NO_MATCH for a prefix of %s", data
[i
].s
);
774 trie
.saveState(state
);
775 UStringTrieResult resultAtState
=trie
.current();
776 UStringTrieResult result
;
777 int32_t valueAtState
=-99;
778 if(USTRINGTRIE_HAS_VALUE(resultAtState
)) {
779 valueAtState
=trie
.getValue();
781 result
=trie
.next(0); // mismatch
782 if(result
!=USTRINGTRIE_NO_MATCH
|| result
!=trie
.current()) {
783 errln("trie.next(0) matched after part of %s", data
[i
].s
);
785 if( resultAtState
!=trie
.resetToState(state
).current() ||
786 (USTRINGTRIE_HAS_VALUE(resultAtState
) && valueAtState
!=trie
.getValue())
788 errln("trie.next(part of %s) changes current()/getValue() after "
789 "saveState/next(0)/resetToState",
791 } else if(!USTRINGTRIE_HAS_VALUE(
792 result
=trie
.next(expectedString
+partialLength
,
793 stringLength
-partialLength
)) ||
794 result
!=trie
.current()) {
795 errln("trie.next(rest of %s) does not seem to contain %s after "
796 "saveState/next(0)/resetToState",
797 data
[i
].s
, data
[i
].s
);
798 } else if(!USTRINGTRIE_HAS_VALUE(
799 result
=trie
.resetToState(state
).
800 next(expectedString
+partialLength
,
801 stringLength
-partialLength
)) ||
802 result
!=trie
.current()) {
803 errln("trie does not seem to contain %s after saveState/next(rest)/resetToState",
805 } else if(trie
.getValue()!=data
[i
].value
) {
806 errln("trie value for %s is %ld=0x%lx instead of expected %ld=0x%lx",
808 (long)trie
.getValue(), (long)trie
.getValue(),
809 (long)data
[i
].value
, (long)data
[i
].value
);
815 // next(string) is also tested in other functions,
816 // but here we try to go partway through the string, and then beyond it.
817 void BytesTrieTest::checkNextString(BytesTrie
&trie
,
818 const StringAndValue data
[], int32_t dataLength
) {
819 for(int32_t i
=0; i
<dataLength
; ++i
) {
820 const char *expectedString
=data
[i
].s
;
821 int32_t stringLength
=strlen(expectedString
);
822 if(!trie
.next(expectedString
, stringLength
/2)) {
823 errln("trie.next(up to middle of string)=USTRINGTRIE_NO_MATCH for %s", data
[i
].s
);
826 // Test that we stop properly at the end of the string.
827 if(trie
.next(expectedString
+stringLength
/2, stringLength
+1-stringLength
/2)) {
828 errln("trie.next(string+NUL)!=USTRINGTRIE_NO_MATCH for %s", data
[i
].s
);
834 void BytesTrieTest::checkIterator(const BytesTrie
&trie
,
835 const StringAndValue data
[], int32_t dataLength
) {
836 IcuTestErrorCode
errorCode(*this, "checkIterator()");
837 BytesTrie::Iterator
iter(trie
, 0, errorCode
);
838 if(errorCode
.logIfFailureAndReset("BytesTrie::Iterator(trie) constructor")) {
841 checkIterator(iter
, data
, dataLength
);
844 void BytesTrieTest::checkIterator(BytesTrie::Iterator
&iter
,
845 const StringAndValue data
[], int32_t dataLength
) {
846 IcuTestErrorCode
errorCode(*this, "checkIterator()");
847 for(int32_t i
=0; i
<dataLength
; ++i
) {
848 if(!iter
.hasNext()) {
849 errln("trie iterator hasNext()=FALSE for item %d: %s", (int)i
, data
[i
].s
);
852 UBool hasNext
=iter
.next(errorCode
);
853 if(errorCode
.logIfFailureAndReset("trie iterator next() for item %d: %s", (int)i
, data
[i
].s
)) {
857 errln("trie iterator next()=FALSE for item %d: %s", (int)i
, data
[i
].s
);
860 if(iter
.getString()!=StringPiece(data
[i
].s
)) {
861 errln("trie iterator next().getString()=%s but expected %s for item %d",
862 iter
.getString().data(), data
[i
].s
, (int)i
);
864 if(iter
.getValue()!=data
[i
].value
) {
865 errln("trie iterator next().getValue()=%ld=0x%lx but expected %ld=0x%lx for item %d: %s",
866 (long)iter
.getValue(), (long)iter
.getValue(),
867 (long)data
[i
].value
, (long)data
[i
].value
,
872 errln("trie iterator hasNext()=TRUE after all items");
874 UBool hasNext
=iter
.next(errorCode
);
875 errorCode
.logIfFailureAndReset("trie iterator next() after all items");
877 errln("trie iterator next()=TRUE after all items");