1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "rtc_base/string_encode.h"
12
13 #include <string.h>
14
15 #include <sstream> // no-presubmit-check TODO(webrtc:8982)
16
17 #include "test/gtest.h"
18
19 namespace rtc {
20
21 class HexEncodeTest : public ::testing::Test {
22 public:
HexEncodeTest()23 HexEncodeTest() : dec_res_(0) {
24 for (size_t i = 0; i < sizeof(data_); ++i) {
25 data_[i] = (i + 128) & 0xff;
26 }
27 memset(decoded_, 0x7f, sizeof(decoded_));
28 }
29
30 char data_[10];
31 char decoded_[11];
32 size_t dec_res_;
33 };
34
35 // Test that we can convert to/from hex with no delimiter.
TEST_F(HexEncodeTest,TestWithNoDelimiter)36 TEST_F(HexEncodeTest, TestWithNoDelimiter) {
37 std::string encoded = hex_encode(data_, sizeof(data_));
38 EXPECT_EQ("80818283848586878889", encoded);
39 dec_res_ =
40 hex_decode(decoded_, sizeof(decoded_), encoded.data(), encoded.size());
41 ASSERT_EQ(sizeof(data_), dec_res_);
42 ASSERT_EQ(0, memcmp(data_, decoded_, dec_res_));
43 }
44
45 // Test that we can convert to/from hex with a colon delimiter.
TEST_F(HexEncodeTest,TestWithDelimiter)46 TEST_F(HexEncodeTest, TestWithDelimiter) {
47 std::string encoded = hex_encode_with_delimiter(data_, sizeof(data_), ':');
48 EXPECT_EQ("80:81:82:83:84:85:86:87:88:89", encoded);
49 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
50 encoded.data(), encoded.size(), ':');
51 ASSERT_EQ(sizeof(data_), dec_res_);
52 ASSERT_EQ(0, memcmp(data_, decoded_, dec_res_));
53 }
54
55 // Test that encoding with one delimiter and decoding with another fails.
TEST_F(HexEncodeTest,TestWithWrongDelimiter)56 TEST_F(HexEncodeTest, TestWithWrongDelimiter) {
57 std::string encoded = hex_encode_with_delimiter(data_, sizeof(data_), ':');
58 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
59 encoded.data(), encoded.size(), '/');
60 ASSERT_EQ(0U, dec_res_);
61 }
62
63 // Test that encoding without a delimiter and decoding with one fails.
TEST_F(HexEncodeTest,TestExpectedDelimiter)64 TEST_F(HexEncodeTest, TestExpectedDelimiter) {
65 std::string encoded = hex_encode(data_, sizeof(data_));
66 EXPECT_EQ(sizeof(data_) * 2, encoded.size());
67 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
68 encoded.data(), encoded.size(), ':');
69 ASSERT_EQ(0U, dec_res_);
70 }
71
72 // Test that encoding with a delimiter and decoding without one fails.
TEST_F(HexEncodeTest,TestExpectedNoDelimiter)73 TEST_F(HexEncodeTest, TestExpectedNoDelimiter) {
74 std::string encoded = hex_encode_with_delimiter(data_, sizeof(data_), ':');
75 EXPECT_EQ(sizeof(data_) * 3 - 1, encoded.size());
76 dec_res_ =
77 hex_decode(decoded_, sizeof(decoded_), encoded.data(), encoded.size());
78 ASSERT_EQ(0U, dec_res_);
79 }
80
81 // Test that we handle a zero-length buffer with no delimiter.
TEST_F(HexEncodeTest,TestZeroLengthNoDelimiter)82 TEST_F(HexEncodeTest, TestZeroLengthNoDelimiter) {
83 std::string encoded = hex_encode("", 0);
84 EXPECT_TRUE(encoded.empty());
85 dec_res_ =
86 hex_decode(decoded_, sizeof(decoded_), encoded.data(), encoded.size());
87 ASSERT_EQ(0U, dec_res_);
88 }
89
90 // Test that we handle a zero-length buffer with a delimiter.
TEST_F(HexEncodeTest,TestZeroLengthWithDelimiter)91 TEST_F(HexEncodeTest, TestZeroLengthWithDelimiter) {
92 std::string encoded = hex_encode_with_delimiter("", 0, ':');
93 EXPECT_TRUE(encoded.empty());
94 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
95 encoded.data(), encoded.size(), ':');
96 ASSERT_EQ(0U, dec_res_);
97 }
98
99 // Test that decoding into a too-small output buffer fails.
TEST_F(HexEncodeTest,TestDecodeTooShort)100 TEST_F(HexEncodeTest, TestDecodeTooShort) {
101 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "0123456789", 10, 0);
102 ASSERT_EQ(0U, dec_res_);
103 ASSERT_EQ(0x7f, decoded_[4]);
104 }
105
106 // Test that decoding non-hex data fails.
TEST_F(HexEncodeTest,TestDecodeBogusData)107 TEST_F(HexEncodeTest, TestDecodeBogusData) {
108 dec_res_ =
109 hex_decode_with_delimiter(decoded_, sizeof(decoded_), "axyz", 4, 0);
110 ASSERT_EQ(0U, dec_res_);
111 }
112
113 // Test that decoding an odd number of hex characters fails.
TEST_F(HexEncodeTest,TestDecodeOddHexDigits)114 TEST_F(HexEncodeTest, TestDecodeOddHexDigits) {
115 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), "012", 3, 0);
116 ASSERT_EQ(0U, dec_res_);
117 }
118
119 // Test that decoding a string with too many delimiters fails.
TEST_F(HexEncodeTest,TestDecodeWithDelimiterTooManyDelimiters)120 TEST_F(HexEncodeTest, TestDecodeWithDelimiterTooManyDelimiters) {
121 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "01::23::45::67", 14, ':');
122 ASSERT_EQ(0U, dec_res_);
123 }
124
125 // Test that decoding a string with a leading delimiter fails.
TEST_F(HexEncodeTest,TestDecodeWithDelimiterLeadingDelimiter)126 TEST_F(HexEncodeTest, TestDecodeWithDelimiterLeadingDelimiter) {
127 dec_res_ = hex_decode_with_delimiter(decoded_, 4, ":01:23:45:67", 12, ':');
128 ASSERT_EQ(0U, dec_res_);
129 }
130
131 // Test that decoding a string with a trailing delimiter fails.
TEST_F(HexEncodeTest,TestDecodeWithDelimiterTrailingDelimiter)132 TEST_F(HexEncodeTest, TestDecodeWithDelimiterTrailingDelimiter) {
133 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "01:23:45:67:", 12, ':');
134 ASSERT_EQ(0U, dec_res_);
135 }
136
137 // Tests counting substrings.
TEST(TokenizeTest,CountSubstrings)138 TEST(TokenizeTest, CountSubstrings) {
139 std::vector<std::string> fields;
140
141 EXPECT_EQ(5ul, tokenize("one two three four five", ' ', &fields));
142 fields.clear();
143 EXPECT_EQ(1ul, tokenize("one", ' ', &fields));
144
145 // Extra spaces should be ignored.
146 fields.clear();
147 EXPECT_EQ(5ul, tokenize(" one two three four five ", ' ', &fields));
148 fields.clear();
149 EXPECT_EQ(1ul, tokenize(" one ", ' ', &fields));
150 fields.clear();
151 EXPECT_EQ(0ul, tokenize(" ", ' ', &fields));
152 }
153
154 // Tests comparing substrings.
TEST(TokenizeTest,CompareSubstrings)155 TEST(TokenizeTest, CompareSubstrings) {
156 std::vector<std::string> fields;
157
158 tokenize("find middle one", ' ', &fields);
159 ASSERT_EQ(3ul, fields.size());
160 ASSERT_STREQ("middle", fields.at(1).c_str());
161 fields.clear();
162
163 // Extra spaces should be ignored.
164 tokenize(" find middle one ", ' ', &fields);
165 ASSERT_EQ(3ul, fields.size());
166 ASSERT_STREQ("middle", fields.at(1).c_str());
167 fields.clear();
168 tokenize(" ", ' ', &fields);
169 ASSERT_EQ(0ul, fields.size());
170 }
171
TEST(TokenizeTest,TokenizeAppend)172 TEST(TokenizeTest, TokenizeAppend) {
173 ASSERT_EQ(0ul, tokenize_append("A B C", ' ', nullptr));
174
175 std::vector<std::string> fields;
176
177 tokenize_append("A B C", ' ', &fields);
178 ASSERT_EQ(3ul, fields.size());
179 ASSERT_STREQ("B", fields.at(1).c_str());
180
181 tokenize_append("D E", ' ', &fields);
182 ASSERT_EQ(5ul, fields.size());
183 ASSERT_STREQ("B", fields.at(1).c_str());
184 ASSERT_STREQ("E", fields.at(4).c_str());
185 }
186
TEST(TokenizeTest,TokenizeWithMarks)187 TEST(TokenizeTest, TokenizeWithMarks) {
188 ASSERT_EQ(0ul, tokenize("D \"A B", ' ', '(', ')', nullptr));
189
190 std::vector<std::string> fields;
191 tokenize("A B C", ' ', '"', '"', &fields);
192 ASSERT_EQ(3ul, fields.size());
193 ASSERT_STREQ("C", fields.at(2).c_str());
194
195 tokenize("\"A B\" C", ' ', '"', '"', &fields);
196 ASSERT_EQ(2ul, fields.size());
197 ASSERT_STREQ("A B", fields.at(0).c_str());
198
199 tokenize("D \"A B\" C", ' ', '"', '"', &fields);
200 ASSERT_EQ(3ul, fields.size());
201 ASSERT_STREQ("D", fields.at(0).c_str());
202 ASSERT_STREQ("A B", fields.at(1).c_str());
203
204 tokenize("D \"A B\" C \"E F\"", ' ', '"', '"', &fields);
205 ASSERT_EQ(4ul, fields.size());
206 ASSERT_STREQ("D", fields.at(0).c_str());
207 ASSERT_STREQ("A B", fields.at(1).c_str());
208 ASSERT_STREQ("E F", fields.at(3).c_str());
209
210 // No matching marks.
211 tokenize("D \"A B", ' ', '"', '"', &fields);
212 ASSERT_EQ(3ul, fields.size());
213 ASSERT_STREQ("D", fields.at(0).c_str());
214 ASSERT_STREQ("\"A", fields.at(1).c_str());
215
216 tokenize("D (A B) C (E F) G", ' ', '(', ')', &fields);
217 ASSERT_EQ(5ul, fields.size());
218 ASSERT_STREQ("D", fields.at(0).c_str());
219 ASSERT_STREQ("A B", fields.at(1).c_str());
220 ASSERT_STREQ("E F", fields.at(3).c_str());
221 }
222
TEST(TokenizeTest,TokenizeWithEmptyTokens)223 TEST(TokenizeTest, TokenizeWithEmptyTokens) {
224 std::vector<std::string> fields;
225 EXPECT_EQ(3ul, tokenize_with_empty_tokens("a.b.c", '.', &fields));
226 EXPECT_EQ("a", fields[0]);
227 EXPECT_EQ("b", fields[1]);
228 EXPECT_EQ("c", fields[2]);
229
230 EXPECT_EQ(3ul, tokenize_with_empty_tokens("..c", '.', &fields));
231 EXPECT_TRUE(fields[0].empty());
232 EXPECT_TRUE(fields[1].empty());
233 EXPECT_EQ("c", fields[2]);
234
235 EXPECT_EQ(1ul, tokenize_with_empty_tokens("", '.', &fields));
236 EXPECT_TRUE(fields[0].empty());
237 }
238
TEST(TokenizeFirstTest,NoLeadingSpaces)239 TEST(TokenizeFirstTest, NoLeadingSpaces) {
240 std::string token;
241 std::string rest;
242
243 ASSERT_TRUE(tokenize_first("A &*${}", ' ', &token, &rest));
244 ASSERT_STREQ("A", token.c_str());
245 ASSERT_STREQ("&*${}", rest.c_str());
246
247 ASSERT_TRUE(tokenize_first("A B& *${}", ' ', &token, &rest));
248 ASSERT_STREQ("A", token.c_str());
249 ASSERT_STREQ("B& *${}", rest.c_str());
250
251 ASSERT_TRUE(tokenize_first("A B& *${} ", ' ', &token, &rest));
252 ASSERT_STREQ("A", token.c_str());
253 ASSERT_STREQ("B& *${} ", rest.c_str());
254 }
255
TEST(TokenizeFirstTest,LeadingSpaces)256 TEST(TokenizeFirstTest, LeadingSpaces) {
257 std::string token;
258 std::string rest;
259
260 ASSERT_TRUE(tokenize_first(" A B C", ' ', &token, &rest));
261 ASSERT_STREQ("", token.c_str());
262 ASSERT_STREQ("A B C", rest.c_str());
263
264 ASSERT_TRUE(tokenize_first(" A B C ", ' ', &token, &rest));
265 ASSERT_STREQ("", token.c_str());
266 ASSERT_STREQ("A B C ", rest.c_str());
267 }
268
TEST(TokenizeFirstTest,SingleToken)269 TEST(TokenizeFirstTest, SingleToken) {
270 std::string token;
271 std::string rest;
272
273 // In the case where we cannot find delimiter the whole string is a token.
274 ASSERT_FALSE(tokenize_first("ABC", ' ', &token, &rest));
275
276 ASSERT_TRUE(tokenize_first("ABC ", ' ', &token, &rest));
277 ASSERT_STREQ("ABC", token.c_str());
278 ASSERT_STREQ("", rest.c_str());
279
280 ASSERT_TRUE(tokenize_first(" ABC ", ' ', &token, &rest));
281 ASSERT_STREQ("", token.c_str());
282 ASSERT_STREQ("ABC ", rest.c_str());
283 }
284
285 // Tests counting substrings.
TEST(SplitTest,CountSubstrings)286 TEST(SplitTest, CountSubstrings) {
287 std::vector<std::string> fields;
288
289 EXPECT_EQ(5ul, split("one,two,three,four,five", ',', &fields));
290 fields.clear();
291 EXPECT_EQ(1ul, split("one", ',', &fields));
292
293 // Empty fields between commas count.
294 fields.clear();
295 EXPECT_EQ(5ul, split("one,,three,four,five", ',', &fields));
296 fields.clear();
297 EXPECT_EQ(3ul, split(",three,", ',', &fields));
298 fields.clear();
299 EXPECT_EQ(1ul, split("", ',', &fields));
300 }
301
302 // Tests comparing substrings.
TEST(SplitTest,CompareSubstrings)303 TEST(SplitTest, CompareSubstrings) {
304 std::vector<std::string> fields;
305
306 split("find,middle,one", ',', &fields);
307 ASSERT_EQ(3ul, fields.size());
308 ASSERT_STREQ("middle", fields.at(1).c_str());
309 fields.clear();
310
311 // Empty fields between commas count.
312 split("find,,middle,one", ',', &fields);
313 ASSERT_EQ(4ul, fields.size());
314 ASSERT_STREQ("middle", fields.at(2).c_str());
315 fields.clear();
316 split("", ',', &fields);
317 ASSERT_EQ(1ul, fields.size());
318 ASSERT_STREQ("", fields.at(0).c_str());
319 }
320
TEST(ToString,SanityCheck)321 TEST(ToString, SanityCheck) {
322 EXPECT_EQ(ToString(true), "true");
323 EXPECT_EQ(ToString(false), "false");
324
325 const char* c = "message";
326 EXPECT_EQ(ToString(c), c);
327 EXPECT_EQ(ToString(std::string(c)), c);
328
329 EXPECT_EQ(ToString(short{-123}), "-123");
330 EXPECT_EQ(ToString((unsigned short)123), "123");
331 EXPECT_EQ(ToString(int{-123}), "-123");
332 EXPECT_EQ(ToString((unsigned int)123), "123");
333 EXPECT_EQ(ToString((long int)-123), "-123");
334 EXPECT_EQ(ToString((unsigned long int)123), "123");
335 EXPECT_EQ(ToString((long long int)-123), "-123");
336 EXPECT_EQ(ToString((unsigned long long int)123), "123");
337
338 int i = 10;
339 int* p = &i;
340 std::ostringstream s; // no-presubmit-check TODO(webrtc:8982)
341 s << p;
342 EXPECT_EQ(s.str(), ToString(p));
343
344 EXPECT_EQ(ToString(0.5), "0.5");
345 }
346
347 template <typename T>
ParsesTo(std::string s,T t)348 void ParsesTo(std::string s, T t) {
349 T value;
350 EXPECT_TRUE(FromString(s, &value));
351 EXPECT_EQ(value, t);
352 }
353
TEST(FromString,DecodeValid)354 TEST(FromString, DecodeValid) {
355 ParsesTo("true", true);
356 ParsesTo("false", false);
357
358 ParsesTo("105", 105);
359 ParsesTo("0.25", 0.25);
360 }
361
362 template <typename T>
FailsToParse(std::string s)363 void FailsToParse(std::string s) {
364 T value;
365 EXPECT_FALSE(FromString(s, &value)) << "[" << s << "]";
366 }
367
TEST(FromString,DecodeInvalid)368 TEST(FromString, DecodeInvalid) {
369 FailsToParse<bool>("True");
370 FailsToParse<bool>("0");
371 FailsToParse<bool>("yes");
372
373 FailsToParse<int>("0.5");
374 FailsToParse<int>("XIV");
375 FailsToParse<double>("");
376 FailsToParse<double>(" ");
377 FailsToParse<int>("1 2");
378 }
379
380 template <typename T>
RoundTrip(T t)381 void RoundTrip(T t) {
382 std::string s = ToString(t);
383 T value;
384 EXPECT_TRUE(FromString(s, &value));
385 EXPECT_EQ(value, t);
386 }
387
TEST(FromString,RoundTrip)388 TEST(FromString, RoundTrip) {
389 RoundTrip<int>(123);
390 RoundTrip(false);
391 RoundTrip(true);
392 RoundTrip(0.5);
393 RoundTrip(-15l);
394 }
395
396 } // namespace rtc
397