1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stddef.h>
6 
7 #include <string>
8 
9 #include <gtest/gtest.h>
10 
11 #include "base/strings/string_piece.h"
12 #include "base/strings/utf_string_conversion_utils.h"
13 
14 namespace base {
15 
16 template <typename T>
17 class CommonStringPieceTest : public ::testing::Test {
18  public:
as_string(const char * input)19   static const T as_string(const char* input) {
20     return T(input);
21   }
as_string(const T & input)22   static const T& as_string(const T& input) {
23     return input;
24   }
25 };
26 
27 typedef ::testing::Types<std::string> SupportedStringTypes;
28 
29 TYPED_TEST_CASE(CommonStringPieceTest, SupportedStringTypes);
30 
TYPED_TEST(CommonStringPieceTest,CheckComparisonOperators)31 TYPED_TEST(CommonStringPieceTest, CheckComparisonOperators) {
32 #define CMP_Y(op, x, y)                                                    \
33   {                                                                        \
34     TypeParam lhs(TestFixture::as_string(x));                              \
35     TypeParam rhs(TestFixture::as_string(y));                              \
36     ASSERT_TRUE( (BasicStringPiece<TypeParam>((lhs.c_str())) op            \
37                   BasicStringPiece<TypeParam>((rhs.c_str()))));            \
38     ASSERT_TRUE( (BasicStringPiece<TypeParam>((lhs.c_str())).compare(      \
39                       BasicStringPiece<TypeParam>((rhs.c_str()))) op 0));  \
40   }
41 
42 #define CMP_N(op, x, y)                                                    \
43   {                                                                        \
44     TypeParam lhs(TestFixture::as_string(x));                              \
45     TypeParam rhs(TestFixture::as_string(y));                              \
46     ASSERT_FALSE( (BasicStringPiece<TypeParam>((lhs.c_str())) op           \
47                   BasicStringPiece<TypeParam>((rhs.c_str()))));            \
48     ASSERT_FALSE( (BasicStringPiece<TypeParam>((lhs.c_str())).compare(     \
49                       BasicStringPiece<TypeParam>((rhs.c_str()))) op 0));  \
50   }
51 
52   CMP_Y(==, "",   "");
53   CMP_Y(==, "a",  "a");
54   CMP_Y(==, "aa", "aa");
55   CMP_N(==, "a",  "");
56   CMP_N(==, "",   "a");
57   CMP_N(==, "a",  "b");
58   CMP_N(==, "a",  "aa");
59   CMP_N(==, "aa", "a");
60 
61   CMP_N(!=, "",   "");
62   CMP_N(!=, "a",  "a");
63   CMP_N(!=, "aa", "aa");
64   CMP_Y(!=, "a",  "");
65   CMP_Y(!=, "",   "a");
66   CMP_Y(!=, "a",  "b");
67   CMP_Y(!=, "a",  "aa");
68   CMP_Y(!=, "aa", "a");
69 
70   CMP_Y(<, "a",  "b");
71   CMP_Y(<, "a",  "aa");
72   CMP_Y(<, "aa", "b");
73   CMP_Y(<, "aa", "bb");
74   CMP_N(<, "a",  "a");
75   CMP_N(<, "b",  "a");
76   CMP_N(<, "aa", "a");
77   CMP_N(<, "b",  "aa");
78   CMP_N(<, "bb", "aa");
79 
80   CMP_Y(<=, "a",  "a");
81   CMP_Y(<=, "a",  "b");
82   CMP_Y(<=, "a",  "aa");
83   CMP_Y(<=, "aa", "b");
84   CMP_Y(<=, "aa", "bb");
85   CMP_N(<=, "b",  "a");
86   CMP_N(<=, "aa", "a");
87   CMP_N(<=, "b",  "aa");
88   CMP_N(<=, "bb", "aa");
89 
90   CMP_N(>=, "a",  "b");
91   CMP_N(>=, "a",  "aa");
92   CMP_N(>=, "aa", "b");
93   CMP_N(>=, "aa", "bb");
94   CMP_Y(>=, "a",  "a");
95   CMP_Y(>=, "b",  "a");
96   CMP_Y(>=, "aa", "a");
97   CMP_Y(>=, "b",  "aa");
98   CMP_Y(>=, "bb", "aa");
99 
100   CMP_N(>, "a",  "a");
101   CMP_N(>, "a",  "b");
102   CMP_N(>, "a",  "aa");
103   CMP_N(>, "aa", "b");
104   CMP_N(>, "aa", "bb");
105   CMP_Y(>, "b",  "a");
106   CMP_Y(>, "aa", "a");
107   CMP_Y(>, "b",  "aa");
108   CMP_Y(>, "bb", "aa");
109 
110   std::string x;
111   for (int i = 0; i < 256; i++) {
112     x += 'a';
113     std::string y = x;
114     CMP_Y(==, x, y);
115     for (int j = 0; j < i; j++) {
116       std::string z = x;
117       z[j] = 'b';       // Differs in position 'j'
118       CMP_N(==, x, z);
119     }
120   }
121 
122 #undef CMP_Y
123 #undef CMP_N
124 }
125 
TYPED_TEST(CommonStringPieceTest,CheckSTL)126 TYPED_TEST(CommonStringPieceTest, CheckSTL) {
127   TypeParam alphabet(TestFixture::as_string("abcdefghijklmnopqrstuvwxyz"));
128   TypeParam abc(TestFixture::as_string("abc"));
129   TypeParam xyz(TestFixture::as_string("xyz"));
130   TypeParam foobar(TestFixture::as_string("foobar"));
131 
132   BasicStringPiece<TypeParam> a(alphabet);
133   BasicStringPiece<TypeParam> b(abc);
134   BasicStringPiece<TypeParam> c(xyz);
135   BasicStringPiece<TypeParam> d(foobar);
136   BasicStringPiece<TypeParam> e;
137   TypeParam temp(TestFixture::as_string("123"));
138   temp += static_cast<typename TypeParam::value_type>(0);
139   temp += TestFixture::as_string("456");
140   BasicStringPiece<TypeParam> f(temp);
141 
142   ASSERT_EQ(a[6], static_cast<typename TypeParam::value_type>('g'));
143   ASSERT_EQ(b[0], static_cast<typename TypeParam::value_type>('a'));
144   ASSERT_EQ(c[2], static_cast<typename TypeParam::value_type>('z'));
145   ASSERT_EQ(f[3], static_cast<typename TypeParam::value_type>('\0'));
146   ASSERT_EQ(f[5], static_cast<typename TypeParam::value_type>('5'));
147 
148   ASSERT_EQ(*d.data(), static_cast<typename TypeParam::value_type>('f'));
149   ASSERT_EQ(d.data()[5], static_cast<typename TypeParam::value_type>('r'));
150   ASSERT_TRUE(e.data() == NULL);
151 
152   ASSERT_EQ(*a.begin(), static_cast<typename TypeParam::value_type>('a'));
153   ASSERT_EQ(*(b.begin() + 2), static_cast<typename TypeParam::value_type>('c'));
154   ASSERT_EQ(*(c.end() - 1), static_cast<typename TypeParam::value_type>('z'));
155 
156   ASSERT_EQ(*a.rbegin(), static_cast<typename TypeParam::value_type>('z'));
157   ASSERT_EQ(*(b.rbegin() + 2),
158             static_cast<typename TypeParam::value_type>('a'));
159   ASSERT_EQ(*(c.rend() - 1), static_cast<typename TypeParam::value_type>('x'));
160   ASSERT_TRUE(a.rbegin() + 26 == a.rend());
161 
162   ASSERT_EQ(a.size(), 26U);
163   ASSERT_EQ(b.size(), 3U);
164   ASSERT_EQ(c.size(), 3U);
165   ASSERT_EQ(d.size(), 6U);
166   ASSERT_EQ(e.size(), 0U);
167   ASSERT_EQ(f.size(), 7U);
168 
169   ASSERT_TRUE(!d.empty());
170   ASSERT_TRUE(d.begin() != d.end());
171   ASSERT_TRUE(d.begin() + 6 == d.end());
172 
173   ASSERT_TRUE(e.empty());
174   ASSERT_TRUE(e.begin() == e.end());
175 
176   d.clear();
177   ASSERT_EQ(d.size(), 0U);
178   ASSERT_TRUE(d.empty());
179   ASSERT_TRUE(d.data() == NULL);
180   ASSERT_TRUE(d.begin() == d.end());
181 
182   ASSERT_GE(a.max_size(), a.capacity());
183   ASSERT_GE(a.capacity(), a.size());
184 }
185 
TYPED_TEST(CommonStringPieceTest,CheckFind)186 TYPED_TEST(CommonStringPieceTest, CheckFind) {
187   typedef BasicStringPiece<TypeParam> Piece;
188 
189   TypeParam alphabet(TestFixture::as_string("abcdefghijklmnopqrstuvwxyz"));
190   TypeParam abc(TestFixture::as_string("abc"));
191   TypeParam xyz(TestFixture::as_string("xyz"));
192   TypeParam foobar(TestFixture::as_string("foobar"));
193 
194   BasicStringPiece<TypeParam> a(alphabet);
195   BasicStringPiece<TypeParam> b(abc);
196   BasicStringPiece<TypeParam> c(xyz);
197   BasicStringPiece<TypeParam> d(foobar);
198 
199   d.clear();
200   Piece e;
201   TypeParam temp(TestFixture::as_string("123"));
202   temp.push_back('\0');
203   temp += TestFixture::as_string("456");
204   Piece f(temp);
205 
206   typename TypeParam::value_type buf[4] = { '%', '%', '%', '%' };
207   ASSERT_EQ(a.copy(buf, 4), 4U);
208   ASSERT_EQ(buf[0], a[0]);
209   ASSERT_EQ(buf[1], a[1]);
210   ASSERT_EQ(buf[2], a[2]);
211   ASSERT_EQ(buf[3], a[3]);
212   ASSERT_EQ(a.copy(buf, 3, 7), 3U);
213   ASSERT_EQ(buf[0], a[7]);
214   ASSERT_EQ(buf[1], a[8]);
215   ASSERT_EQ(buf[2], a[9]);
216   ASSERT_EQ(buf[3], a[3]);
217   ASSERT_EQ(c.copy(buf, 99), 3U);
218   ASSERT_EQ(buf[0], c[0]);
219   ASSERT_EQ(buf[1], c[1]);
220   ASSERT_EQ(buf[2], c[2]);
221   ASSERT_EQ(buf[3], a[3]);
222 
223   ASSERT_EQ(Piece::npos, TypeParam::npos);
224 
225   ASSERT_EQ(a.find(b), 0U);
226   ASSERT_EQ(a.find(b, 1), Piece::npos);
227   ASSERT_EQ(a.find(c), 23U);
228   ASSERT_EQ(a.find(c, 9), 23U);
229   ASSERT_EQ(a.find(c, Piece::npos), Piece::npos);
230   ASSERT_EQ(b.find(c), Piece::npos);
231   ASSERT_EQ(b.find(c, Piece::npos), Piece::npos);
232   ASSERT_EQ(a.find(d), 0U);
233   ASSERT_EQ(a.find(e), 0U);
234   ASSERT_EQ(a.find(d, 12), 12U);
235   ASSERT_EQ(a.find(e, 17), 17U);
236   TypeParam not_found(TestFixture::as_string("xx not found bb"));
237   Piece g(not_found);
238   ASSERT_EQ(a.find(g), Piece::npos);
239   // empty string nonsense
240   ASSERT_EQ(d.find(b), Piece::npos);
241   ASSERT_EQ(e.find(b), Piece::npos);
242   ASSERT_EQ(d.find(b, 4), Piece::npos);
243   ASSERT_EQ(e.find(b, 7), Piece::npos);
244 
245   size_t empty_search_pos = TypeParam().find(TypeParam());
246   ASSERT_EQ(d.find(d), empty_search_pos);
247   ASSERT_EQ(d.find(e), empty_search_pos);
248   ASSERT_EQ(e.find(d), empty_search_pos);
249   ASSERT_EQ(e.find(e), empty_search_pos);
250   ASSERT_EQ(d.find(d, 4), std::string().find(std::string(), 4));
251   ASSERT_EQ(d.find(e, 4), std::string().find(std::string(), 4));
252   ASSERT_EQ(e.find(d, 4), std::string().find(std::string(), 4));
253   ASSERT_EQ(e.find(e, 4), std::string().find(std::string(), 4));
254 
255   ASSERT_EQ(a.find('a'), 0U);
256   ASSERT_EQ(a.find('c'), 2U);
257   ASSERT_EQ(a.find('z'), 25U);
258   ASSERT_EQ(a.find('$'), Piece::npos);
259   ASSERT_EQ(a.find('\0'), Piece::npos);
260   ASSERT_EQ(f.find('\0'), 3U);
261   ASSERT_EQ(f.find('3'), 2U);
262   ASSERT_EQ(f.find('5'), 5U);
263   ASSERT_EQ(g.find('o'), 4U);
264   ASSERT_EQ(g.find('o', 4), 4U);
265   ASSERT_EQ(g.find('o', 5), 8U);
266   ASSERT_EQ(a.find('b', 5), Piece::npos);
267   // empty string nonsense
268   ASSERT_EQ(d.find('\0'), Piece::npos);
269   ASSERT_EQ(e.find('\0'), Piece::npos);
270   ASSERT_EQ(d.find('\0', 4), Piece::npos);
271   ASSERT_EQ(e.find('\0', 7), Piece::npos);
272   ASSERT_EQ(d.find('x'), Piece::npos);
273   ASSERT_EQ(e.find('x'), Piece::npos);
274   ASSERT_EQ(d.find('x', 4), Piece::npos);
275   ASSERT_EQ(e.find('x', 7), Piece::npos);
276 
277   ASSERT_EQ(a.rfind(b), 0U);
278   ASSERT_EQ(a.rfind(b, 1), 0U);
279   ASSERT_EQ(a.rfind(c), 23U);
280   ASSERT_EQ(a.rfind(c, 22U), Piece::npos);
281   ASSERT_EQ(a.rfind(c, 1U), Piece::npos);
282   ASSERT_EQ(a.rfind(c, 0U), Piece::npos);
283   ASSERT_EQ(b.rfind(c), Piece::npos);
284   ASSERT_EQ(b.rfind(c, 0U), Piece::npos);
285   ASSERT_EQ(a.rfind(d), static_cast<size_t>(a.as_string().rfind(TypeParam())));
286   ASSERT_EQ(a.rfind(e), a.as_string().rfind(TypeParam()));
287   ASSERT_EQ(a.rfind(d, 12), 12U);
288   ASSERT_EQ(a.rfind(e, 17), 17U);
289   ASSERT_EQ(a.rfind(g), Piece::npos);
290   ASSERT_EQ(d.rfind(b), Piece::npos);
291   ASSERT_EQ(e.rfind(b), Piece::npos);
292   ASSERT_EQ(d.rfind(b, 4), Piece::npos);
293   ASSERT_EQ(e.rfind(b, 7), Piece::npos);
294   // empty string nonsense
295   ASSERT_EQ(d.rfind(d, 4), std::string().rfind(std::string()));
296   ASSERT_EQ(e.rfind(d, 7), std::string().rfind(std::string()));
297   ASSERT_EQ(d.rfind(e, 4), std::string().rfind(std::string()));
298   ASSERT_EQ(e.rfind(e, 7), std::string().rfind(std::string()));
299   ASSERT_EQ(d.rfind(d), std::string().rfind(std::string()));
300   ASSERT_EQ(e.rfind(d), std::string().rfind(std::string()));
301   ASSERT_EQ(d.rfind(e), std::string().rfind(std::string()));
302   ASSERT_EQ(e.rfind(e), std::string().rfind(std::string()));
303 
304   ASSERT_EQ(g.rfind('o'), 8U);
305   ASSERT_EQ(g.rfind('q'), Piece::npos);
306   ASSERT_EQ(g.rfind('o', 8), 8U);
307   ASSERT_EQ(g.rfind('o', 7), 4U);
308   ASSERT_EQ(g.rfind('o', 3), Piece::npos);
309   ASSERT_EQ(f.rfind('\0'), 3U);
310   ASSERT_EQ(f.rfind('\0', 12), 3U);
311   ASSERT_EQ(f.rfind('3'), 2U);
312   ASSERT_EQ(f.rfind('5'), 5U);
313   // empty string nonsense
314   ASSERT_EQ(d.rfind('o'), Piece::npos);
315   ASSERT_EQ(e.rfind('o'), Piece::npos);
316   ASSERT_EQ(d.rfind('o', 4), Piece::npos);
317   ASSERT_EQ(e.rfind('o', 7), Piece::npos);
318 
319   TypeParam one_two_three_four(TestFixture::as_string("one,two:three;four"));
320   TypeParam comma_colon(TestFixture::as_string(",:"));
321   ASSERT_EQ(3U, Piece(one_two_three_four).find_first_of(comma_colon));
322   ASSERT_EQ(a.find_first_of(b), 0U);
323   ASSERT_EQ(a.find_first_of(b, 0), 0U);
324   ASSERT_EQ(a.find_first_of(b, 1), 1U);
325   ASSERT_EQ(a.find_first_of(b, 2), 2U);
326   ASSERT_EQ(a.find_first_of(b, 3), Piece::npos);
327   ASSERT_EQ(a.find_first_of(c), 23U);
328   ASSERT_EQ(a.find_first_of(c, 23), 23U);
329   ASSERT_EQ(a.find_first_of(c, 24), 24U);
330   ASSERT_EQ(a.find_first_of(c, 25), 25U);
331   ASSERT_EQ(a.find_first_of(c, 26), Piece::npos);
332   ASSERT_EQ(g.find_first_of(b), 13U);
333   ASSERT_EQ(g.find_first_of(c), 0U);
334   ASSERT_EQ(a.find_first_of(f), Piece::npos);
335   ASSERT_EQ(f.find_first_of(a), Piece::npos);
336   // empty string nonsense
337   ASSERT_EQ(a.find_first_of(d), Piece::npos);
338   ASSERT_EQ(a.find_first_of(e), Piece::npos);
339   ASSERT_EQ(d.find_first_of(b), Piece::npos);
340   ASSERT_EQ(e.find_first_of(b), Piece::npos);
341   ASSERT_EQ(d.find_first_of(d), Piece::npos);
342   ASSERT_EQ(e.find_first_of(d), Piece::npos);
343   ASSERT_EQ(d.find_first_of(e), Piece::npos);
344   ASSERT_EQ(e.find_first_of(e), Piece::npos);
345 
346   ASSERT_EQ(a.find_first_not_of(b), 3U);
347   ASSERT_EQ(a.find_first_not_of(c), 0U);
348   ASSERT_EQ(b.find_first_not_of(a), Piece::npos);
349   ASSERT_EQ(c.find_first_not_of(a), Piece::npos);
350   ASSERT_EQ(f.find_first_not_of(a), 0U);
351   ASSERT_EQ(a.find_first_not_of(f), 0U);
352   ASSERT_EQ(a.find_first_not_of(d), 0U);
353   ASSERT_EQ(a.find_first_not_of(e), 0U);
354   // empty string nonsense
355   ASSERT_EQ(d.find_first_not_of(a), Piece::npos);
356   ASSERT_EQ(e.find_first_not_of(a), Piece::npos);
357   ASSERT_EQ(d.find_first_not_of(d), Piece::npos);
358   ASSERT_EQ(e.find_first_not_of(d), Piece::npos);
359   ASSERT_EQ(d.find_first_not_of(e), Piece::npos);
360   ASSERT_EQ(e.find_first_not_of(e), Piece::npos);
361 
362   TypeParam equals(TestFixture::as_string("===="));
363   Piece h(equals);
364   ASSERT_EQ(h.find_first_not_of('='), Piece::npos);
365   ASSERT_EQ(h.find_first_not_of('=', 3), Piece::npos);
366   ASSERT_EQ(h.find_first_not_of('\0'), 0U);
367   ASSERT_EQ(g.find_first_not_of('x'), 2U);
368   ASSERT_EQ(f.find_first_not_of('\0'), 0U);
369   ASSERT_EQ(f.find_first_not_of('\0', 3), 4U);
370   ASSERT_EQ(f.find_first_not_of('\0', 2), 2U);
371   // empty string nonsense
372   ASSERT_EQ(d.find_first_not_of('x'), Piece::npos);
373   ASSERT_EQ(e.find_first_not_of('x'), Piece::npos);
374   ASSERT_EQ(d.find_first_not_of('\0'), Piece::npos);
375   ASSERT_EQ(e.find_first_not_of('\0'), Piece::npos);
376 
377   //  Piece g("xx not found bb");
378   TypeParam fifty_six(TestFixture::as_string("56"));
379   Piece i(fifty_six);
380   ASSERT_EQ(h.find_last_of(a), Piece::npos);
381   ASSERT_EQ(g.find_last_of(a), g.size()-1);
382   ASSERT_EQ(a.find_last_of(b), 2U);
383   ASSERT_EQ(a.find_last_of(c), a.size()-1);
384   ASSERT_EQ(f.find_last_of(i), 6U);
385   ASSERT_EQ(a.find_last_of('a'), 0U);
386   ASSERT_EQ(a.find_last_of('b'), 1U);
387   ASSERT_EQ(a.find_last_of('z'), 25U);
388   ASSERT_EQ(a.find_last_of('a', 5), 0U);
389   ASSERT_EQ(a.find_last_of('b', 5), 1U);
390   ASSERT_EQ(a.find_last_of('b', 0), Piece::npos);
391   ASSERT_EQ(a.find_last_of('z', 25), 25U);
392   ASSERT_EQ(a.find_last_of('z', 24), Piece::npos);
393   ASSERT_EQ(f.find_last_of(i, 5), 5U);
394   ASSERT_EQ(f.find_last_of(i, 6), 6U);
395   ASSERT_EQ(f.find_last_of(a, 4), Piece::npos);
396   // empty string nonsense
397   ASSERT_EQ(f.find_last_of(d), Piece::npos);
398   ASSERT_EQ(f.find_last_of(e), Piece::npos);
399   ASSERT_EQ(f.find_last_of(d, 4), Piece::npos);
400   ASSERT_EQ(f.find_last_of(e, 4), Piece::npos);
401   ASSERT_EQ(d.find_last_of(d), Piece::npos);
402   ASSERT_EQ(d.find_last_of(e), Piece::npos);
403   ASSERT_EQ(e.find_last_of(d), Piece::npos);
404   ASSERT_EQ(e.find_last_of(e), Piece::npos);
405   ASSERT_EQ(d.find_last_of(f), Piece::npos);
406   ASSERT_EQ(e.find_last_of(f), Piece::npos);
407   ASSERT_EQ(d.find_last_of(d, 4), Piece::npos);
408   ASSERT_EQ(d.find_last_of(e, 4), Piece::npos);
409   ASSERT_EQ(e.find_last_of(d, 4), Piece::npos);
410   ASSERT_EQ(e.find_last_of(e, 4), Piece::npos);
411   ASSERT_EQ(d.find_last_of(f, 4), Piece::npos);
412   ASSERT_EQ(e.find_last_of(f, 4), Piece::npos);
413 
414   ASSERT_EQ(a.find_last_not_of(b), a.size()-1);
415   ASSERT_EQ(a.find_last_not_of(c), 22U);
416   ASSERT_EQ(b.find_last_not_of(a), Piece::npos);
417   ASSERT_EQ(b.find_last_not_of(b), Piece::npos);
418   ASSERT_EQ(f.find_last_not_of(i), 4U);
419   ASSERT_EQ(a.find_last_not_of(c, 24), 22U);
420   ASSERT_EQ(a.find_last_not_of(b, 3), 3U);
421   ASSERT_EQ(a.find_last_not_of(b, 2), Piece::npos);
422   // empty string nonsense
423   ASSERT_EQ(f.find_last_not_of(d), f.size()-1);
424   ASSERT_EQ(f.find_last_not_of(e), f.size()-1);
425   ASSERT_EQ(f.find_last_not_of(d, 4), 4U);
426   ASSERT_EQ(f.find_last_not_of(e, 4), 4U);
427   ASSERT_EQ(d.find_last_not_of(d), Piece::npos);
428   ASSERT_EQ(d.find_last_not_of(e), Piece::npos);
429   ASSERT_EQ(e.find_last_not_of(d), Piece::npos);
430   ASSERT_EQ(e.find_last_not_of(e), Piece::npos);
431   ASSERT_EQ(d.find_last_not_of(f), Piece::npos);
432   ASSERT_EQ(e.find_last_not_of(f), Piece::npos);
433   ASSERT_EQ(d.find_last_not_of(d, 4), Piece::npos);
434   ASSERT_EQ(d.find_last_not_of(e, 4), Piece::npos);
435   ASSERT_EQ(e.find_last_not_of(d, 4), Piece::npos);
436   ASSERT_EQ(e.find_last_not_of(e, 4), Piece::npos);
437   ASSERT_EQ(d.find_last_not_of(f, 4), Piece::npos);
438   ASSERT_EQ(e.find_last_not_of(f, 4), Piece::npos);
439 
440   ASSERT_EQ(h.find_last_not_of('x'), h.size() - 1);
441   ASSERT_EQ(h.find_last_not_of('='), Piece::npos);
442   ASSERT_EQ(b.find_last_not_of('c'), 1U);
443   ASSERT_EQ(h.find_last_not_of('x', 2), 2U);
444   ASSERT_EQ(h.find_last_not_of('=', 2), Piece::npos);
445   ASSERT_EQ(b.find_last_not_of('b', 1), 0U);
446   // empty string nonsense
447   ASSERT_EQ(d.find_last_not_of('x'), Piece::npos);
448   ASSERT_EQ(e.find_last_not_of('x'), Piece::npos);
449   ASSERT_EQ(d.find_last_not_of('\0'), Piece::npos);
450   ASSERT_EQ(e.find_last_not_of('\0'), Piece::npos);
451 
452   ASSERT_EQ(a.substr(0, 3), b);
453   ASSERT_EQ(a.substr(23), c);
454   ASSERT_EQ(a.substr(23, 3), c);
455   ASSERT_EQ(a.substr(23, 99), c);
456   ASSERT_EQ(a.substr(0), a);
457   ASSERT_EQ(a.substr(3, 2), TestFixture::as_string("de"));
458   // empty string nonsense
459   ASSERT_EQ(a.substr(99, 2), e);
460   ASSERT_EQ(d.substr(99), e);
461   ASSERT_EQ(d.substr(0, 99), e);
462   ASSERT_EQ(d.substr(99, 99), e);
463 }
464 
TYPED_TEST(CommonStringPieceTest,CheckCustom)465 TYPED_TEST(CommonStringPieceTest, CheckCustom) {
466   TypeParam foobar(TestFixture::as_string("foobar"));
467   BasicStringPiece<TypeParam> a(foobar);
468   TypeParam s1(TestFixture::as_string("123"));
469   s1 += static_cast<typename TypeParam::value_type>('\0');
470   s1 += TestFixture::as_string("456");
471   BasicStringPiece<TypeParam> b(s1);
472   BasicStringPiece<TypeParam> e;
473   TypeParam s2;
474 
475   // remove_prefix
476   BasicStringPiece<TypeParam> c(a);
477   c.remove_prefix(3);
478   ASSERT_EQ(c, TestFixture::as_string("bar"));
479   c = a;
480   c.remove_prefix(0);
481   ASSERT_EQ(c, a);
482   c.remove_prefix(c.size());
483   ASSERT_EQ(c, e);
484 
485   // remove_suffix
486   c = a;
487   c.remove_suffix(3);
488   ASSERT_EQ(c, TestFixture::as_string("foo"));
489   c = a;
490   c.remove_suffix(0);
491   ASSERT_EQ(c, a);
492   c.remove_suffix(c.size());
493   ASSERT_EQ(c, e);
494 
495   // set
496   c.set(foobar.c_str());
497   ASSERT_EQ(c, a);
498   c.set(foobar.c_str(), 6);
499   ASSERT_EQ(c, a);
500   c.set(foobar.c_str(), 0);
501   ASSERT_EQ(c, e);
502   c.set(foobar.c_str(), 7);  // Note, has an embedded NULL
503   ASSERT_NE(c, a);
504 
505   // as_string
506   TypeParam s3(a.as_string().c_str(), 7);  // Note, has an embedded NULL
507   ASSERT_TRUE(c == s3);
508   TypeParam s4(e.as_string());
509   ASSERT_TRUE(s4.empty());
510 }
511 
TEST(StringPieceTest,CheckCustom)512 TEST(StringPieceTest, CheckCustom) {
513   StringPiece a("foobar");
514   std::string s1("123");
515   s1 += '\0';
516   s1 += "456";
517   StringPiece b(s1);
518   StringPiece e;
519   std::string s2;
520 
521   // CopyToString
522   a.CopyToString(&s2);
523   ASSERT_EQ(s2.size(), 6U);
524   ASSERT_EQ(s2, "foobar");
525   b.CopyToString(&s2);
526   ASSERT_EQ(s2.size(), 7U);
527   ASSERT_EQ(s1, s2);
528   e.CopyToString(&s2);
529   ASSERT_TRUE(s2.empty());
530 
531   // AppendToString
532   s2.erase();
533   a.AppendToString(&s2);
534   ASSERT_EQ(s2.size(), 6U);
535   ASSERT_EQ(s2, "foobar");
536   a.AppendToString(&s2);
537   ASSERT_EQ(s2.size(), 12U);
538   ASSERT_EQ(s2, "foobarfoobar");
539 
540   // starts_with
541   ASSERT_TRUE(a.starts_with(a));
542   ASSERT_TRUE(a.starts_with("foo"));
543   ASSERT_TRUE(a.starts_with(e));
544   ASSERT_TRUE(b.starts_with(s1));
545   ASSERT_TRUE(b.starts_with(b));
546   ASSERT_TRUE(b.starts_with(e));
547   ASSERT_TRUE(e.starts_with(""));
548   ASSERT_TRUE(!a.starts_with(b));
549   ASSERT_TRUE(!b.starts_with(a));
550   ASSERT_TRUE(!e.starts_with(a));
551 
552   // ends with
553   ASSERT_TRUE(a.ends_with(a));
554   ASSERT_TRUE(a.ends_with("bar"));
555   ASSERT_TRUE(a.ends_with(e));
556   ASSERT_TRUE(b.ends_with(s1));
557   ASSERT_TRUE(b.ends_with(b));
558   ASSERT_TRUE(b.ends_with(e));
559   ASSERT_TRUE(e.ends_with(""));
560   ASSERT_TRUE(!a.ends_with(b));
561   ASSERT_TRUE(!b.ends_with(a));
562   ASSERT_TRUE(!e.ends_with(a));
563 
564   StringPiece c;
565   c.set("foobar", 6);
566   ASSERT_EQ(c, a);
567   c.set("foobar", 0);
568   ASSERT_EQ(c, e);
569   c.set("foobar", 7);
570   ASSERT_NE(c, a);
571 }
572 
TYPED_TEST(CommonStringPieceTest,CheckNULL)573 TYPED_TEST(CommonStringPieceTest, CheckNULL) {
574   // we used to crash here, but now we don't.
575   BasicStringPiece<TypeParam> s(NULL);
576   ASSERT_EQ(s.data(), (const typename TypeParam::value_type*)NULL);
577   ASSERT_EQ(s.size(), 0U);
578 
579   s.set(NULL);
580   ASSERT_EQ(s.data(), (const typename TypeParam::value_type*)NULL);
581   ASSERT_EQ(s.size(), 0U);
582 
583   TypeParam str = s.as_string();
584   ASSERT_EQ(str.length(), 0U);
585   ASSERT_EQ(str, TypeParam());
586 }
587 
TYPED_TEST(CommonStringPieceTest,CheckComparisons2)588 TYPED_TEST(CommonStringPieceTest, CheckComparisons2) {
589   TypeParam alphabet(TestFixture::as_string("abcdefghijklmnopqrstuvwxyz"));
590   TypeParam alphabet_z(TestFixture::as_string("abcdefghijklmnopqrstuvwxyzz"));
591   TypeParam alphabet_y(TestFixture::as_string("abcdefghijklmnopqrstuvwxyy"));
592   BasicStringPiece<TypeParam> abc(alphabet);
593 
594   // check comparison operations on strings longer than 4 bytes.
595   ASSERT_TRUE(abc == BasicStringPiece<TypeParam>(alphabet));
596   ASSERT_EQ(abc.compare(BasicStringPiece<TypeParam>(alphabet)), 0);
597 
598   ASSERT_TRUE(abc < BasicStringPiece<TypeParam>(alphabet_z));
599   ASSERT_LT(abc.compare(BasicStringPiece<TypeParam>(alphabet_z)), 0);
600 
601   ASSERT_TRUE(abc > BasicStringPiece<TypeParam>(alphabet_y));
602   ASSERT_GT(abc.compare(BasicStringPiece<TypeParam>(alphabet_y)), 0);
603 }
604 
605 // Test operations only supported by std::string version.
TEST(StringPieceTest,CheckComparisons2)606 TEST(StringPieceTest, CheckComparisons2) {
607   StringPiece abc("abcdefghijklmnopqrstuvwxyz");
608 
609   // starts_with
610   ASSERT_TRUE(abc.starts_with(abc));
611   ASSERT_TRUE(abc.starts_with("abcdefghijklm"));
612   ASSERT_TRUE(!abc.starts_with("abcdefguvwxyz"));
613 
614   // ends_with
615   ASSERT_TRUE(abc.ends_with(abc));
616   ASSERT_TRUE(!abc.ends_with("abcdefguvwxyz"));
617   ASSERT_TRUE(abc.ends_with("nopqrstuvwxyz"));
618 }
619 
TYPED_TEST(CommonStringPieceTest,StringCompareNotAmbiguous)620 TYPED_TEST(CommonStringPieceTest, StringCompareNotAmbiguous) {
621   ASSERT_TRUE(TestFixture::as_string("hello").c_str() ==
622               TestFixture::as_string("hello"));
623   ASSERT_TRUE(TestFixture::as_string("hello").c_str() <
624               TestFixture::as_string("world"));
625 }
626 
TYPED_TEST(CommonStringPieceTest,HeterogenousStringPieceEquals)627 TYPED_TEST(CommonStringPieceTest, HeterogenousStringPieceEquals) {
628   TypeParam hello(TestFixture::as_string("hello"));
629 
630   ASSERT_TRUE(BasicStringPiece<TypeParam>(hello) == hello);
631   ASSERT_TRUE(hello.c_str() == BasicStringPiece<TypeParam>(hello));
632 }
633 
TYPED_TEST(CommonStringPieceTest,CheckConstructors)634 TYPED_TEST(CommonStringPieceTest, CheckConstructors) {
635   TypeParam str(TestFixture::as_string("hello world"));
636   TypeParam empty;
637 
638   ASSERT_TRUE(str == BasicStringPiece<TypeParam>(str));
639   ASSERT_TRUE(str == BasicStringPiece<TypeParam>(str.c_str()));
640   ASSERT_TRUE(TestFixture::as_string("hello") ==
641               BasicStringPiece<TypeParam>(str.c_str(), 5));
642   ASSERT_TRUE(empty == BasicStringPiece<TypeParam>(str.c_str(),
643       static_cast<typename BasicStringPiece<TypeParam>::size_type>(0)));
644   ASSERT_TRUE(empty == BasicStringPiece<TypeParam>(NULL));
645   ASSERT_TRUE(empty == BasicStringPiece<TypeParam>(NULL,
646       static_cast<typename BasicStringPiece<TypeParam>::size_type>(0)));
647   ASSERT_TRUE(empty == BasicStringPiece<TypeParam>());
648   ASSERT_TRUE(str == BasicStringPiece<TypeParam>(str.begin(), str.end()));
649   ASSERT_TRUE(empty == BasicStringPiece<TypeParam>(str.begin(), str.begin()));
650   ASSERT_TRUE(empty == BasicStringPiece<TypeParam>(empty));
651   ASSERT_TRUE(empty == BasicStringPiece<TypeParam>(empty.begin(), empty.end()));
652 }
653 
654 }  // namespace base
655