xref: /aosp_15_r20/external/icing/icing/util/character-iterator_test.cc (revision 8b6cd535a057e39b3b86660c4aa06c99747c2136)
1*8b6cd535SAndroid Build Coastguard Worker // Copyright (C) 2019 Google LLC
2*8b6cd535SAndroid Build Coastguard Worker //
3*8b6cd535SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*8b6cd535SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*8b6cd535SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*8b6cd535SAndroid Build Coastguard Worker //
7*8b6cd535SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
8*8b6cd535SAndroid Build Coastguard Worker //
9*8b6cd535SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*8b6cd535SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*8b6cd535SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*8b6cd535SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*8b6cd535SAndroid Build Coastguard Worker // limitations under the License.
14*8b6cd535SAndroid Build Coastguard Worker 
15*8b6cd535SAndroid Build Coastguard Worker #include "icing/util/character-iterator.h"
16*8b6cd535SAndroid Build Coastguard Worker 
17*8b6cd535SAndroid Build Coastguard Worker #include "gmock/gmock.h"
18*8b6cd535SAndroid Build Coastguard Worker #include "gtest/gtest.h"
19*8b6cd535SAndroid Build Coastguard Worker #include "icing/testing/icu-i18n-test-utils.h"
20*8b6cd535SAndroid Build Coastguard Worker 
21*8b6cd535SAndroid Build Coastguard Worker namespace icing {
22*8b6cd535SAndroid Build Coastguard Worker namespace lib {
23*8b6cd535SAndroid Build Coastguard Worker 
24*8b6cd535SAndroid Build Coastguard Worker using ::testing::Eq;
25*8b6cd535SAndroid Build Coastguard Worker using ::testing::IsFalse;
26*8b6cd535SAndroid Build Coastguard Worker using ::testing::IsTrue;
27*8b6cd535SAndroid Build Coastguard Worker 
TEST(CharacterIteratorTest,BasicUtf8)28*8b6cd535SAndroid Build Coastguard Worker TEST(CharacterIteratorTest, BasicUtf8) {
29*8b6cd535SAndroid Build Coastguard Worker   constexpr std::string_view kText = "¿Dónde está la biblioteca?";
30*8b6cd535SAndroid Build Coastguard Worker   CharacterIterator iterator(kText);
31*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("¿"));
32*8b6cd535SAndroid Build Coastguard Worker 
33*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf8(4), IsTrue());
34*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("ó"));
35*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
36*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/3, /*utf16_index=*/2,
37*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/2)));
38*8b6cd535SAndroid Build Coastguard Worker 
39*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf8(18), IsTrue());
40*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("b"));
41*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
42*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/18, /*utf16_index=*/15,
43*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/15)));
44*8b6cd535SAndroid Build Coastguard Worker 
45*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf8(28), IsTrue());
46*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("?"));
47*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
48*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/28, /*utf16_index=*/25,
49*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/25)));
50*8b6cd535SAndroid Build Coastguard Worker 
51*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf8(29), IsTrue());
52*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.GetCurrentChar(), Eq(0));
53*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
54*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/29, /*utf16_index=*/26,
55*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/26)));
56*8b6cd535SAndroid Build Coastguard Worker 
57*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf8(28), IsTrue());
58*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("?"));
59*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
60*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/28, /*utf16_index=*/25,
61*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/25)));
62*8b6cd535SAndroid Build Coastguard Worker 
63*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf8(18), IsTrue());
64*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("b"));
65*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
66*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/18, /*utf16_index=*/15,
67*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/15)));
68*8b6cd535SAndroid Build Coastguard Worker 
69*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf8(4), IsTrue());
70*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("ó"));
71*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
72*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/3, /*utf16_index=*/2,
73*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/2)));
74*8b6cd535SAndroid Build Coastguard Worker 
75*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf8(0), IsTrue());
76*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("¿"));
77*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
78*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/0, /*utf16_index=*/0,
79*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/0)));
80*8b6cd535SAndroid Build Coastguard Worker }
81*8b6cd535SAndroid Build Coastguard Worker 
TEST(CharacterIteratorTest,BasicUtf16)82*8b6cd535SAndroid Build Coastguard Worker TEST(CharacterIteratorTest, BasicUtf16) {
83*8b6cd535SAndroid Build Coastguard Worker   constexpr std::string_view kText = "¿Dónde está la biblioteca?";
84*8b6cd535SAndroid Build Coastguard Worker   CharacterIterator iterator(kText);
85*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("¿"));
86*8b6cd535SAndroid Build Coastguard Worker 
87*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf16(2), IsTrue());
88*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("ó"));
89*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
90*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/3, /*utf16_index=*/2,
91*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/2)));
92*8b6cd535SAndroid Build Coastguard Worker 
93*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf16(15), IsTrue());
94*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("b"));
95*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
96*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/18, /*utf16_index=*/15,
97*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/15)));
98*8b6cd535SAndroid Build Coastguard Worker 
99*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf16(25), IsTrue());
100*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("?"));
101*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
102*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/28, /*utf16_index=*/25,
103*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/25)));
104*8b6cd535SAndroid Build Coastguard Worker 
105*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf16(26), IsTrue());
106*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.GetCurrentChar(), Eq(0));
107*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
108*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/29, /*utf16_index=*/26,
109*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/26)));
110*8b6cd535SAndroid Build Coastguard Worker 
111*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf16(25), IsTrue());
112*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("?"));
113*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
114*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/28, /*utf16_index=*/25,
115*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/25)));
116*8b6cd535SAndroid Build Coastguard Worker 
117*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf16(15), IsTrue());
118*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("b"));
119*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
120*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/18, /*utf16_index=*/15,
121*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/15)));
122*8b6cd535SAndroid Build Coastguard Worker 
123*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf16(2), IsTrue());
124*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("ó"));
125*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
126*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/3, /*utf16_index=*/2,
127*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/2)));
128*8b6cd535SAndroid Build Coastguard Worker 
129*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf8(0), IsTrue());
130*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("¿"));
131*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
132*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/0, /*utf16_index=*/0,
133*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/0)));
134*8b6cd535SAndroid Build Coastguard Worker }
135*8b6cd535SAndroid Build Coastguard Worker 
TEST(CharacterIteratorTest,BasicUtf32)136*8b6cd535SAndroid Build Coastguard Worker TEST(CharacterIteratorTest, BasicUtf32) {
137*8b6cd535SAndroid Build Coastguard Worker   constexpr std::string_view kText = "¿Dónde está la biblioteca?";
138*8b6cd535SAndroid Build Coastguard Worker   CharacterIterator iterator(kText);
139*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("¿"));
140*8b6cd535SAndroid Build Coastguard Worker 
141*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf32(2), IsTrue());
142*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("ó"));
143*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
144*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/3, /*utf16_index=*/2,
145*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/2)));
146*8b6cd535SAndroid Build Coastguard Worker 
147*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf32(15), IsTrue());
148*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("b"));
149*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
150*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/18, /*utf16_index=*/15,
151*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/15)));
152*8b6cd535SAndroid Build Coastguard Worker 
153*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf32(25), IsTrue());
154*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("?"));
155*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
156*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/28, /*utf16_index=*/25,
157*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/25)));
158*8b6cd535SAndroid Build Coastguard Worker 
159*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf32(26), IsTrue());
160*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.GetCurrentChar(), Eq(0));
161*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
162*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/29, /*utf16_index=*/26,
163*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/26)));
164*8b6cd535SAndroid Build Coastguard Worker 
165*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf32(25), IsTrue());
166*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("?"));
167*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
168*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/28, /*utf16_index=*/25,
169*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/25)));
170*8b6cd535SAndroid Build Coastguard Worker 
171*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf32(15), IsTrue());
172*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("b"));
173*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
174*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/18, /*utf16_index=*/15,
175*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/15)));
176*8b6cd535SAndroid Build Coastguard Worker 
177*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf32(2), IsTrue());
178*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("ó"));
179*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
180*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/3, /*utf16_index=*/2,
181*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/2)));
182*8b6cd535SAndroid Build Coastguard Worker 
183*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf32(0), IsTrue());
184*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("¿"));
185*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator,
186*8b6cd535SAndroid Build Coastguard Worker               Eq(CharacterIterator(kText, /*utf8_index=*/0, /*utf16_index=*/0,
187*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/0)));
188*8b6cd535SAndroid Build Coastguard Worker }
189*8b6cd535SAndroid Build Coastguard Worker 
TEST(CharacterIteratorTest,InvalidUtf)190*8b6cd535SAndroid Build Coastguard Worker TEST(CharacterIteratorTest, InvalidUtf) {
191*8b6cd535SAndroid Build Coastguard Worker   // "\255" is an invalid sequence.
192*8b6cd535SAndroid Build Coastguard Worker   constexpr std::string_view kText = "foo \255 bar";
193*8b6cd535SAndroid Build Coastguard Worker   CharacterIterator iterator(kText);
194*8b6cd535SAndroid Build Coastguard Worker 
195*8b6cd535SAndroid Build Coastguard Worker   // Try to advance to the 'b' in 'bar'. This will fail and leave us pointed at
196*8b6cd535SAndroid Build Coastguard Worker   // the invalid sequence '\255'. Get CurrentChar() should return an invalid
197*8b6cd535SAndroid Build Coastguard Worker   // character.
198*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf8(6), IsFalse());
199*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.GetCurrentChar(), Eq(i18n_utils::kInvalidUChar32));
200*8b6cd535SAndroid Build Coastguard Worker   CharacterIterator exp_iterator(kText, /*utf8_index=*/4, /*utf16_index=*/4,
201*8b6cd535SAndroid Build Coastguard Worker                                  /*utf32_index=*/4);
202*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator, Eq(exp_iterator));
203*8b6cd535SAndroid Build Coastguard Worker 
204*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf16(6), IsFalse());
205*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.GetCurrentChar(), Eq(i18n_utils::kInvalidUChar32));
206*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator, Eq(exp_iterator));
207*8b6cd535SAndroid Build Coastguard Worker 
208*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.AdvanceToUtf32(6), IsFalse());
209*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.GetCurrentChar(), Eq(i18n_utils::kInvalidUChar32));
210*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator, Eq(exp_iterator));
211*8b6cd535SAndroid Build Coastguard Worker 
212*8b6cd535SAndroid Build Coastguard Worker   // Create the iterator with it pointing at the 'b' in 'bar'.
213*8b6cd535SAndroid Build Coastguard Worker   iterator = CharacterIterator(kText, /*utf8_index=*/6, /*utf16_index=*/6,
214*8b6cd535SAndroid Build Coastguard Worker                                /*utf32_index=*/6);
215*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator.GetCurrentChar()), Eq("b"));
216*8b6cd535SAndroid Build Coastguard Worker 
217*8b6cd535SAndroid Build Coastguard Worker   // Try to advance to the last 'o' in 'foo'. This will fail and leave us
218*8b6cd535SAndroid Build Coastguard Worker   // pointed at the ' ' before the invalid sequence '\255'.
219*8b6cd535SAndroid Build Coastguard Worker   exp_iterator = CharacterIterator(kText, /*utf8_index=*/5, /*utf16_index=*/5,
220*8b6cd535SAndroid Build Coastguard Worker                                    /*utf32_index=*/5);
221*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf8(2), IsFalse());
222*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.GetCurrentChar(), Eq(' '));
223*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator, Eq(exp_iterator));
224*8b6cd535SAndroid Build Coastguard Worker 
225*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf16(2), IsFalse());
226*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.GetCurrentChar(), Eq(' '));
227*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator, Eq(exp_iterator));
228*8b6cd535SAndroid Build Coastguard Worker 
229*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.RewindToUtf32(2), IsFalse());
230*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator.GetCurrentChar(), Eq(' '));
231*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator, Eq(exp_iterator));
232*8b6cd535SAndroid Build Coastguard Worker }
233*8b6cd535SAndroid Build Coastguard Worker 
TEST(CharacterIteratorTest,MoveToUtfNegativeIndex)234*8b6cd535SAndroid Build Coastguard Worker TEST(CharacterIteratorTest, MoveToUtfNegativeIndex) {
235*8b6cd535SAndroid Build Coastguard Worker   constexpr std::string_view kText = "¿Dónde está la biblioteca?";
236*8b6cd535SAndroid Build Coastguard Worker 
237*8b6cd535SAndroid Build Coastguard Worker   CharacterIterator iterator_utf8(kText, /*utf8_index=*/-1, /*utf16_index=*/0,
238*8b6cd535SAndroid Build Coastguard Worker                              /*utf32_index=*/0);
239*8b6cd535SAndroid Build Coastguard Worker   // We should be able to successfully move when the index is negative.
240*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf8.MoveToUtf8(0), IsTrue());
241*8b6cd535SAndroid Build Coastguard Worker   // The character cache should be reset and contain the first character when
242*8b6cd535SAndroid Build Coastguard Worker   // resetting to index 0.
243*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator_utf8.GetCurrentChar()), Eq("¿"));
244*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf8.utf8_index(), Eq(0));
245*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf8.utf16_index(), Eq(0));
246*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf8.utf32_index(), Eq(0));
247*8b6cd535SAndroid Build Coastguard Worker 
248*8b6cd535SAndroid Build Coastguard Worker   CharacterIterator iterator_utf16(kText, /*utf8_index=*/0, /*utf16_index=*/-1,
249*8b6cd535SAndroid Build Coastguard Worker                              /*utf32_index=*/0);
250*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf16.MoveToUtf16(1), IsTrue());
251*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf16.GetCurrentChar(), Eq('D'));
252*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf16.utf8_index(), Eq(2));
253*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf16.utf16_index(), Eq(1));
254*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf16.utf32_index(), Eq(1));
255*8b6cd535SAndroid Build Coastguard Worker 
256*8b6cd535SAndroid Build Coastguard Worker   CharacterIterator iterator_utf32(kText, /*utf8_index=*/0, /*utf16_index=*/0,
257*8b6cd535SAndroid Build Coastguard Worker                              /*utf32_index=*/-1);
258*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf32.MoveToUtf32(2), IsTrue());
259*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(UCharToString(iterator_utf32.GetCurrentChar()), Eq("ó"));
260*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf32.utf8_index(), Eq(3));
261*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf32.utf16_index(), Eq(2));
262*8b6cd535SAndroid Build Coastguard Worker   EXPECT_THAT(iterator_utf32.utf32_index(), Eq(2));
263*8b6cd535SAndroid Build Coastguard Worker }
264*8b6cd535SAndroid Build Coastguard Worker 
265*8b6cd535SAndroid Build Coastguard Worker }  // namespace lib
266*8b6cd535SAndroid Build Coastguard Worker }  // namespace icing
267