1 /* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/core/platform/tstring.h"
17
18 #include <memory>
19 #include <string>
20
21 #include "tensorflow/core/platform/cord.h"
22 #include "tensorflow/core/platform/stringpiece.h"
23 #include "tensorflow/core/platform/test.h"
24
25 using tensorflow::tstring;
26
27 static const char kLongString[] =
28 "abcdefghij"
29 "klmnopqrst"
30 "uvwxyz0123"
31 "456789ABCD"
32 "EFGHIKLMNO";
33 const size_t kLongStringLen = sizeof(kLongString) / sizeof(char) - sizeof(char);
34
TEST(TF_TStringTest,Construction)35 TEST(TF_TStringTest, Construction) {
36 tstring s10;
37 tstring s11("a\0a", 3);
38 tstring s12(kLongString);
39 tstring s13(3, 'b');
40 tstring s14(tensorflow::StringPiece("hi"));
41 tstring s15(std::string("bye"));
42
43 EXPECT_EQ("", s10);
44 EXPECT_TRUE(s10.empty());
45 EXPECT_EQ(tstring::Type::SMALL, s10.type());
46 EXPECT_EQ(0, s10.size());
47 EXPECT_EQ(0, s10.length());
48 EXPECT_EQ(TF_TString_SmallCapacity, s10.capacity());
49
50 EXPECT_EQ(std::string("a\0a", 3), s11);
51 EXPECT_FALSE(s11.empty());
52 EXPECT_EQ(3, s11.size());
53 EXPECT_EQ(3, s11.length());
54 EXPECT_EQ(kLongString, s12);
55 EXPECT_EQ(kLongStringLen, s12.size());
56 EXPECT_EQ(tstring::Type::LARGE, s12.type());
57 EXPECT_LT(TF_TString_SmallCapacity, s12.capacity());
58 EXPECT_EQ("bbb", s13);
59 EXPECT_EQ("hi", s14);
60 EXPECT_EQ(tstring::Type::SMALL, s14.type());
61 EXPECT_EQ("bye", s15);
62 }
63
TEST(TF_TStringTest,CopyMove)64 TEST(TF_TStringTest, CopyMove) {
65 tstring s20(kLongString);
66 tstring s21(s20);
67 tstring s22;
68
69 EXPECT_EQ(s20, s21);
70
71 s22 = std::move(s21);
72
73 EXPECT_EQ(s20, s22);
74 EXPECT_EQ("", s21); // NOLINT
75 EXPECT_EQ(tstring::Type::SMALL, s21.type());
76 }
77
TEST(TF_TStringTest,Assignment)78 TEST(TF_TStringTest, Assignment) {
79 tstring s30("123456789012345678901234567890");
80 tstring s31;
81 tstring s32;
82
83 s31 = s30;
84
85 EXPECT_EQ(s30, s31);
86 EXPECT_EQ(tstring::Type::LARGE, s31.type());
87 EXPECT_EQ(s30.size(), s31.size());
88
89 s32 = std::move(s30);
90
91 EXPECT_EQ(s31, s32);
92 EXPECT_EQ("", s30); // NOLINT
93 EXPECT_EQ(tstring::Type::SMALL, s30.type());
94 EXPECT_EQ(tstring::Type::LARGE, s32.type());
95
96 s32 = tstring::view(kLongString);
97
98 EXPECT_EQ(kLongString, s32);
99 EXPECT_EQ(tstring::Type::VIEW, s32.type());
100 EXPECT_EQ(kLongStringLen, s32.size());
101 EXPECT_EQ(0, s32.capacity());
102
103 tstring s33(std::move(s32));
104
105 EXPECT_EQ(kLongString, s33);
106 EXPECT_EQ(tstring::Type::VIEW, s33.type());
107 EXPECT_EQ(kLongStringLen, s33.size());
108
109 s32 = std::string(kLongString);
110
111 EXPECT_EQ(kLongString, s32);
112 EXPECT_EQ(tstring::Type::LARGE, s32.type());
113 EXPECT_EQ(kLongStringLen, s32.size());
114
115 // LARGE -> SMALL
116 s32 = "hello";
117
118 EXPECT_EQ("hello", s32);
119 EXPECT_EQ(tstring::Type::SMALL, s32.type());
120 EXPECT_EQ(5, s32.size());
121
122 s33 = 'a';
123
124 EXPECT_EQ("a", s33);
125 EXPECT_EQ(tstring::Type::SMALL, s33.type());
126 EXPECT_EQ(1, s33.size());
127
128 s32 = tensorflow::StringPiece(kLongString);
129
130 EXPECT_EQ(kLongString, s32);
131 EXPECT_EQ(tstring::Type::LARGE, s32.type());
132 EXPECT_EQ(kLongStringLen, s32.size());
133
134 // LARGE -> SMALL but still LARGE
135 s32.resize(TF_TString_SmallCapacity * 2);
136
137 EXPECT_EQ(tensorflow::StringPiece(kLongString, TF_TString_SmallCapacity * 2),
138 s32);
139 EXPECT_EQ(tstring::Type::LARGE, s32.type());
140 EXPECT_EQ(TF_TString_SmallCapacity * 2, s32.size());
141
142 s32 = tstring::view(kLongString, kLongStringLen);
143
144 EXPECT_EQ(kLongString, s32);
145 EXPECT_EQ(tstring::Type::VIEW, s32.type());
146 EXPECT_EQ(kLongStringLen, s32.size());
147
148 s32.assign("hello1");
149
150 EXPECT_EQ("hello1", s32);
151
152 s32.assign("hello2", 5);
153
154 EXPECT_EQ("hello", s32);
155
156 s30.assign_as_view(kLongString);
157
158 EXPECT_EQ(tstring::Type::VIEW, s30.type());
159
160 s31.assign_as_view(s30);
161
162 EXPECT_EQ(tstring::Type::VIEW, s31.type());
163
164 EXPECT_EQ(kLongString, s30.c_str());
165 EXPECT_EQ(kLongString, s31.c_str());
166
167 std::string tmp(kLongString);
168 s32.assign_as_view(tmp);
169
170 EXPECT_EQ(tstring::Type::VIEW, s32.type());
171 EXPECT_STREQ(kLongString, s32.c_str());
172
173 s33.assign_as_view(kLongString, 2);
174
175 EXPECT_EQ(2, s33.size());
176
177 s32.assign_as_view(tensorflow::StringPiece(kLongString));
178
179 EXPECT_EQ(tstring::Type::VIEW, s32.type());
180 EXPECT_EQ(kLongString, s32.c_str());
181
182 #ifdef PLATFORM_GOOGLE
183 s33 = absl::Cord(kLongString);
184
185 EXPECT_EQ(kLongString, s33);
186 EXPECT_EQ(tstring::Type::LARGE, s33.type());
187 EXPECT_EQ(kLongStringLen, s33.size());
188
189 tstring s34((absl::Cord(kLongString)));
190
191 EXPECT_EQ(kLongString, s34);
192 EXPECT_EQ(tstring::Type::LARGE, s34.type());
193 EXPECT_EQ(kLongStringLen, s34.size());
194 #endif // PLATFORM_GOOGLE
195 }
196
TEST(TF_TStringTest,Comparison)197 TEST(TF_TStringTest, Comparison) {
198 tstring empty("");
199 tstring a("a");
200 tstring aa("aa");
201 tstring a_("a");
202 tstring b("b");
203 const char c[] = "c";
204 tstring nulla("\0a", 2);
205 tstring nullb("\0b", 2);
206 tstring nullaa("\0aa", 3);
207
208 EXPECT_TRUE(a < b);
209 EXPECT_TRUE(a != b);
210 EXPECT_FALSE(a > b);
211 EXPECT_FALSE(a == b);
212
213 EXPECT_TRUE(a < aa);
214 EXPECT_TRUE(a != aa);
215 EXPECT_FALSE(a > aa);
216 EXPECT_FALSE(a == aa);
217
218 EXPECT_TRUE(b > a);
219 EXPECT_TRUE(b != a);
220 EXPECT_FALSE(b < a);
221 EXPECT_FALSE(b == a);
222 EXPECT_FALSE(a == b);
223
224 EXPECT_FALSE(b == c);
225 EXPECT_TRUE(b != c);
226
227 EXPECT_TRUE(empty < a);
228 EXPECT_TRUE(empty != a);
229 EXPECT_FALSE(empty > a);
230 EXPECT_FALSE(empty == a);
231
232 EXPECT_TRUE(a > empty);
233 EXPECT_TRUE(a != empty);
234 EXPECT_FALSE(a < empty);
235 EXPECT_FALSE(a == empty);
236
237 EXPECT_FALSE(a < a_);
238 EXPECT_FALSE(a != a_);
239 EXPECT_FALSE(a > a_);
240 EXPECT_TRUE(a == a_);
241
242 EXPECT_TRUE(nulla < nullaa);
243 EXPECT_TRUE(nulla != nullaa);
244 EXPECT_FALSE(nulla > nullaa);
245 EXPECT_FALSE(nulla == nullaa);
246
247 EXPECT_TRUE(nulla < nullb);
248
249 EXPECT_TRUE(nullaa > nulla);
250 EXPECT_TRUE(nullaa != nulla);
251 EXPECT_FALSE(nullaa < nulla);
252 EXPECT_FALSE(nullaa == nulla);
253 }
254
TEST(TF_TStringTest,Conversion)255 TEST(TF_TStringTest, Conversion) {
256 tstring s50(kLongString);
257 std::string s51(s50);
258 tensorflow::StringPiece s52(s50);
259 EXPECT_EQ(kLongString, s51);
260 EXPECT_EQ(kLongStringLen, s51.size());
261 EXPECT_EQ(kLongString, s52);
262 EXPECT_EQ(kLongStringLen, s52.size());
263
264 #ifdef PLATFORM_GOOGLE
265 absl::AlphaNum s53(s50);
266
267 EXPECT_STREQ(kLongString, s53.data());
268 EXPECT_EQ(kLongStringLen, s53.size());
269 #endif // PLATFORM_GOOGLE
270 }
271
TEST(TF_TStringTest,Allocation)272 TEST(TF_TStringTest, Allocation) {
273 tstring s60;
274
275 s60.resize(2);
276
277 EXPECT_EQ(std::string("\0\0", 2), s60);
278 EXPECT_EQ(2, s60.size());
279 EXPECT_EQ(2, s60.length());
280
281 s60.resize(6, 'a');
282
283 EXPECT_EQ(std::string("\0\0aaaa", 6), s60);
284 EXPECT_EQ(6, s60.size());
285 EXPECT_EQ(6, s60.length());
286
287 s60.resize(3, 'b');
288
289 EXPECT_EQ(std::string("\0\0a", 3), s60);
290 EXPECT_EQ(3, s60.size());
291 EXPECT_EQ(3, s60.length());
292
293 s60.clear();
294 EXPECT_EQ("", s60);
295 EXPECT_TRUE(s60.empty());
296 EXPECT_EQ(0, s60.size());
297 EXPECT_EQ(0, s60.length());
298
299 s60.reserve(100);
300 // 16-byte alignment 7*16-1 = 111
301 EXPECT_EQ(111, s60.capacity());
302 s60.reserve(100);
303 }
304
TEST(TF_TStringTest,ElementAccess)305 TEST(TF_TStringTest, ElementAccess) {
306 tstring s70(kLongString);
307
308 EXPECT_STREQ(kLongString, s70.data());
309 EXPECT_EQ(s70.data(), s70.c_str());
310
311 for (size_t i = 0; i < s70.size(); i++) {
312 EXPECT_EQ(kLongString[i], s70.data()[i]);
313 }
314
315 tstring::const_iterator i = s70.begin();
316 const char* j = kLongString;
317 for (; *j != '\0'; i++, j++) {
318 EXPECT_EQ(*j, *i);
319 }
320 EXPECT_EQ('\0', *s70.end());
321 EXPECT_EQ(*i, *s70.end());
322 EXPECT_EQ(*(i - 1), s70.back());
323 }
324
TEST(TF_TStringTest,Modifiers)325 TEST(TF_TStringTest, Modifiers) {
326 // Modifiers
327 tstring s80("ba");
328 tstring s81;
329 tstring s82(kLongString);
330
331 s81.append(s80);
332
333 EXPECT_EQ("ba", s81);
334
335 s81.append(s80);
336
337 EXPECT_EQ("baba", s81);
338
339 s81.append("\0c", 2);
340
341 EXPECT_EQ(std::string("baba\0c", 6), s81);
342
343 s81.append("dd");
344
345 EXPECT_EQ(std::string("baba\0cdd", 8), s81);
346
347 s81.append(3, 'z');
348
349 EXPECT_EQ(tstring("baba\0cddzzz", 11), s81);
350
351 s81.append(0, 'z');
352 s81.append("dd", 0);
353 s81.append("");
354 s81.append(tstring());
355
356 EXPECT_EQ(std::string("baba\0cddzzz", 11), s81);
357
358 s81.erase(0, 1);
359
360 EXPECT_EQ(std::string("aba\0cddzzz", 10), s81);
361
362 s81.erase(4, 6);
363
364 EXPECT_EQ(std::string("aba\0", 4), s81);
365
366 s81.insert(1, tstring("\0moo\0", 5), 1, 4);
367
368 EXPECT_EQ(std::string("amoo\0ba\0", 8), s81);
369
370 s81.insert(0, 2, '\0');
371 s81.insert(s81.size() - 1, 1, 'q');
372
373 EXPECT_EQ(std::string("\0\0amoo\0baq\0", 11), s81);
374
375 s81.erase(0, s81.size());
376
377 EXPECT_EQ(tstring(), s81);
378
379 s80.swap(s82);
380
381 EXPECT_EQ(kLongString, s80);
382 EXPECT_EQ("ba", s82);
383
384 s82.push_back('\0');
385 s82.push_back('q');
386
387 EXPECT_EQ(std::string("ba\0q", 4), s82);
388 }
389
TEST(TF_TStringTest,Friends)390 TEST(TF_TStringTest, Friends) {
391 tstring s90("b");
392 tstring s91("\0a\0", 3);
393 tstring s92;
394
395 EXPECT_EQ("b", s90 + s92);
396 EXPECT_EQ("b", s92 + s90);
397
398 EXPECT_EQ(std::string("\0a\0", 3), s92 + s91);
399 EXPECT_EQ(std::string("\0a\0", 3), s91 + s92);
400
401 EXPECT_EQ(std::string("b\0a\0", 4), s90 + s91);
402 EXPECT_EQ(std::string("\0a\0b", 4), s91 + s90);
403
404 std::stringstream ss;
405 ss << s91;
406
407 EXPECT_EQ(std::string("\0a\0", 3), ss.str());
408 }
409