blob: 9bdc592c29aa0663778ae2c7d86dca601819b1f4 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_base/stringencode.h"
12#include "rtc_base/arraysize.h"
13#include "rtc_base/gunit.h"
14#include "rtc_base/stringutils.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000015
Jonas Olsson6b1985d2018-07-05 11:59:48 +020016#include <sstream> // no-presubmit-check TODO(webrtc:8982)
17
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000018namespace rtc {
19
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000020class HexEncodeTest : public testing::Test {
21 public:
22 HexEncodeTest() : enc_res_(0), dec_res_(0) {
23 for (size_t i = 0; i < sizeof(data_); ++i) {
24 data_[i] = (i + 128) & 0xff;
25 }
26 memset(decoded_, 0x7f, sizeof(decoded_));
27 }
28
29 char data_[10];
30 char encoded_[31];
31 char decoded_[11];
32 size_t enc_res_;
33 size_t dec_res_;
34};
35
36// Test that we can convert to/from hex with no delimiter.
37TEST_F(HexEncodeTest, TestWithNoDelimiter) {
38 enc_res_ = hex_encode(encoded_, sizeof(encoded_), data_, sizeof(data_));
39 ASSERT_EQ(sizeof(data_) * 2, enc_res_);
40 ASSERT_STREQ("80818283848586878889", encoded_);
41 dec_res_ = hex_decode(decoded_, sizeof(decoded_), encoded_, enc_res_);
42 ASSERT_EQ(sizeof(data_), dec_res_);
43 ASSERT_EQ(0, memcmp(data_, decoded_, dec_res_));
44}
45
46// Test that we can convert to/from hex with a colon delimiter.
47TEST_F(HexEncodeTest, TestWithDelimiter) {
Yves Gerey665174f2018-06-19 15:03:05 +020048 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(encoded_), data_,
49 sizeof(data_), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000050 ASSERT_EQ(sizeof(data_) * 3 - 1, enc_res_);
51 ASSERT_STREQ("80:81:82:83:84:85:86:87:88:89", encoded_);
Yves Gerey665174f2018-06-19 15:03:05 +020052 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), encoded_,
53 enc_res_, ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000054 ASSERT_EQ(sizeof(data_), dec_res_);
55 ASSERT_EQ(0, memcmp(data_, decoded_, dec_res_));
56}
57
58// Test that encoding with one delimiter and decoding with another fails.
59TEST_F(HexEncodeTest, TestWithWrongDelimiter) {
Yves Gerey665174f2018-06-19 15:03:05 +020060 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(encoded_), data_,
61 sizeof(data_), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000062 ASSERT_EQ(sizeof(data_) * 3 - 1, enc_res_);
Yves Gerey665174f2018-06-19 15:03:05 +020063 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), encoded_,
64 enc_res_, '/');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000065 ASSERT_EQ(0U, dec_res_);
66}
67
68// Test that encoding without a delimiter and decoding with one fails.
69TEST_F(HexEncodeTest, TestExpectedDelimiter) {
70 enc_res_ = hex_encode(encoded_, sizeof(encoded_), data_, sizeof(data_));
71 ASSERT_EQ(sizeof(data_) * 2, enc_res_);
Yves Gerey665174f2018-06-19 15:03:05 +020072 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), encoded_,
73 enc_res_, ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000074 ASSERT_EQ(0U, dec_res_);
75}
76
77// Test that encoding with a delimiter and decoding without one fails.
78TEST_F(HexEncodeTest, TestExpectedNoDelimiter) {
Yves Gerey665174f2018-06-19 15:03:05 +020079 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(encoded_), data_,
80 sizeof(data_), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000081 ASSERT_EQ(sizeof(data_) * 3 - 1, enc_res_);
82 dec_res_ = hex_decode(decoded_, sizeof(decoded_), encoded_, enc_res_);
83 ASSERT_EQ(0U, dec_res_);
84}
85
86// Test that we handle a zero-length buffer with no delimiter.
87TEST_F(HexEncodeTest, TestZeroLengthNoDelimiter) {
88 enc_res_ = hex_encode(encoded_, sizeof(encoded_), "", 0);
89 ASSERT_EQ(0U, enc_res_);
90 dec_res_ = hex_decode(decoded_, sizeof(decoded_), encoded_, enc_res_);
91 ASSERT_EQ(0U, dec_res_);
92}
93
94// Test that we handle a zero-length buffer with a delimiter.
95TEST_F(HexEncodeTest, TestZeroLengthWithDelimiter) {
96 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(encoded_), "", 0, ':');
97 ASSERT_EQ(0U, enc_res_);
Yves Gerey665174f2018-06-19 15:03:05 +020098 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), encoded_,
99 enc_res_, ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000100 ASSERT_EQ(0U, dec_res_);
101}
102
103// Test the std::string variants that take no delimiter.
104TEST_F(HexEncodeTest, TestHelpersNoDelimiter) {
105 std::string result = hex_encode(data_, sizeof(data_));
106 ASSERT_EQ("80818283848586878889", result);
107 dec_res_ = hex_decode(decoded_, sizeof(decoded_), result);
108 ASSERT_EQ(sizeof(data_), dec_res_);
109 ASSERT_EQ(0, memcmp(data_, decoded_, dec_res_));
110}
111
112// Test the std::string variants that use a delimiter.
113TEST_F(HexEncodeTest, TestHelpersWithDelimiter) {
114 std::string result = hex_encode_with_delimiter(data_, sizeof(data_), ':');
115 ASSERT_EQ("80:81:82:83:84:85:86:87:88:89", result);
116 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), result, ':');
117 ASSERT_EQ(sizeof(data_), dec_res_);
118 ASSERT_EQ(0, memcmp(data_, decoded_, dec_res_));
119}
120
121// Test that encoding into a too-small output buffer (without delimiter) fails.
122TEST_F(HexEncodeTest, TestEncodeTooShort) {
Yves Gerey665174f2018-06-19 15:03:05 +0200123 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(data_) * 2, data_,
124 sizeof(data_), 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000125 ASSERT_EQ(0U, enc_res_);
126}
127
128// Test that encoding into a too-small output buffer (with delimiter) fails.
129TEST_F(HexEncodeTest, TestEncodeWithDelimiterTooShort) {
Yves Gerey665174f2018-06-19 15:03:05 +0200130 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(data_) * 3 - 1, data_,
131 sizeof(data_), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000132 ASSERT_EQ(0U, enc_res_);
133}
134
135// Test that decoding into a too-small output buffer fails.
136TEST_F(HexEncodeTest, TestDecodeTooShort) {
137 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "0123456789", 10, 0);
138 ASSERT_EQ(0U, dec_res_);
139 ASSERT_EQ(0x7f, decoded_[4]);
140}
141
142// Test that decoding non-hex data fails.
143TEST_F(HexEncodeTest, TestDecodeBogusData) {
144 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), "xyz", 3, 0);
145 ASSERT_EQ(0U, dec_res_);
146}
147
148// Test that decoding an odd number of hex characters fails.
149TEST_F(HexEncodeTest, TestDecodeOddHexDigits) {
150 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), "012", 3, 0);
151 ASSERT_EQ(0U, dec_res_);
152}
153
154// Test that decoding a string with too many delimiters fails.
155TEST_F(HexEncodeTest, TestDecodeWithDelimiterTooManyDelimiters) {
156 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "01::23::45::67", 14, ':');
157 ASSERT_EQ(0U, dec_res_);
158}
159
160// Test that decoding a string with a leading delimiter fails.
161TEST_F(HexEncodeTest, TestDecodeWithDelimiterLeadingDelimiter) {
162 dec_res_ = hex_decode_with_delimiter(decoded_, 4, ":01:23:45:67", 12, ':');
163 ASSERT_EQ(0U, dec_res_);
164}
165
166// Test that decoding a string with a trailing delimiter fails.
167TEST_F(HexEncodeTest, TestDecodeWithDelimiterTrailingDelimiter) {
168 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "01:23:45:67:", 12, ':');
169 ASSERT_EQ(0U, dec_res_);
170}
171
172// Tests counting substrings.
173TEST(TokenizeTest, CountSubstrings) {
174 std::vector<std::string> fields;
175
176 EXPECT_EQ(5ul, tokenize("one two three four five", ' ', &fields));
177 fields.clear();
178 EXPECT_EQ(1ul, tokenize("one", ' ', &fields));
179
180 // Extra spaces should be ignored.
181 fields.clear();
182 EXPECT_EQ(5ul, tokenize(" one two three four five ", ' ', &fields));
183 fields.clear();
184 EXPECT_EQ(1ul, tokenize(" one ", ' ', &fields));
185 fields.clear();
186 EXPECT_EQ(0ul, tokenize(" ", ' ', &fields));
187}
188
189// Tests comparing substrings.
190TEST(TokenizeTest, CompareSubstrings) {
191 std::vector<std::string> fields;
192
193 tokenize("find middle one", ' ', &fields);
194 ASSERT_EQ(3ul, fields.size());
195 ASSERT_STREQ("middle", fields.at(1).c_str());
196 fields.clear();
197
198 // Extra spaces should be ignored.
199 tokenize(" find middle one ", ' ', &fields);
200 ASSERT_EQ(3ul, fields.size());
201 ASSERT_STREQ("middle", fields.at(1).c_str());
202 fields.clear();
203 tokenize(" ", ' ', &fields);
204 ASSERT_EQ(0ul, fields.size());
205}
206
207TEST(TokenizeTest, TokenizeAppend) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800208 ASSERT_EQ(0ul, tokenize_append("A B C", ' ', nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000209
210 std::vector<std::string> fields;
211
212 tokenize_append("A B C", ' ', &fields);
213 ASSERT_EQ(3ul, fields.size());
214 ASSERT_STREQ("B", fields.at(1).c_str());
215
216 tokenize_append("D E", ' ', &fields);
217 ASSERT_EQ(5ul, fields.size());
218 ASSERT_STREQ("B", fields.at(1).c_str());
219 ASSERT_STREQ("E", fields.at(4).c_str());
220}
221
222TEST(TokenizeTest, TokenizeWithMarks) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800223 ASSERT_EQ(0ul, tokenize("D \"A B", ' ', '(', ')', nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000224
225 std::vector<std::string> fields;
226 tokenize("A B C", ' ', '"', '"', &fields);
227 ASSERT_EQ(3ul, fields.size());
228 ASSERT_STREQ("C", fields.at(2).c_str());
229
230 tokenize("\"A B\" C", ' ', '"', '"', &fields);
231 ASSERT_EQ(2ul, fields.size());
232 ASSERT_STREQ("A B", fields.at(0).c_str());
233
234 tokenize("D \"A B\" C", ' ', '"', '"', &fields);
235 ASSERT_EQ(3ul, fields.size());
236 ASSERT_STREQ("D", fields.at(0).c_str());
237 ASSERT_STREQ("A B", fields.at(1).c_str());
238
239 tokenize("D \"A B\" C \"E F\"", ' ', '"', '"', &fields);
240 ASSERT_EQ(4ul, fields.size());
241 ASSERT_STREQ("D", fields.at(0).c_str());
242 ASSERT_STREQ("A B", fields.at(1).c_str());
243 ASSERT_STREQ("E F", fields.at(3).c_str());
244
245 // No matching marks.
246 tokenize("D \"A B", ' ', '"', '"', &fields);
247 ASSERT_EQ(3ul, fields.size());
248 ASSERT_STREQ("D", fields.at(0).c_str());
249 ASSERT_STREQ("\"A", fields.at(1).c_str());
250
251 tokenize("D (A B) C (E F) G", ' ', '(', ')', &fields);
252 ASSERT_EQ(5ul, fields.size());
253 ASSERT_STREQ("D", fields.at(0).c_str());
254 ASSERT_STREQ("A B", fields.at(1).c_str());
255 ASSERT_STREQ("E F", fields.at(3).c_str());
256}
257
deadbeef0a6c4ca2015-10-06 11:38:28 -0700258TEST(TokenizeTest, TokenizeWithEmptyTokens) {
259 std::vector<std::string> fields;
260 EXPECT_EQ(3ul, tokenize_with_empty_tokens("a.b.c", '.', &fields));
261 EXPECT_EQ("a", fields[0]);
262 EXPECT_EQ("b", fields[1]);
263 EXPECT_EQ("c", fields[2]);
264
265 EXPECT_EQ(3ul, tokenize_with_empty_tokens("..c", '.', &fields));
266 EXPECT_TRUE(fields[0].empty());
267 EXPECT_TRUE(fields[1].empty());
268 EXPECT_EQ("c", fields[2]);
269
270 EXPECT_EQ(1ul, tokenize_with_empty_tokens("", '.', &fields));
271 EXPECT_TRUE(fields[0].empty());
272}
273
Donald Curtis0e07f922015-05-15 09:21:23 -0700274TEST(TokenizeFirstTest, NoLeadingSpaces) {
275 std::string token;
276 std::string rest;
277
278 ASSERT_TRUE(tokenize_first("A &*${}", ' ', &token, &rest));
279 ASSERT_STREQ("A", token.c_str());
280 ASSERT_STREQ("&*${}", rest.c_str());
281
282 ASSERT_TRUE(tokenize_first("A B& *${}", ' ', &token, &rest));
283 ASSERT_STREQ("A", token.c_str());
284 ASSERT_STREQ("B& *${}", rest.c_str());
285
286 ASSERT_TRUE(tokenize_first("A B& *${} ", ' ', &token, &rest));
287 ASSERT_STREQ("A", token.c_str());
288 ASSERT_STREQ("B& *${} ", rest.c_str());
289}
290
291TEST(TokenizeFirstTest, LeadingSpaces) {
292 std::string token;
293 std::string rest;
294
295 ASSERT_TRUE(tokenize_first(" A B C", ' ', &token, &rest));
296 ASSERT_STREQ("", token.c_str());
297 ASSERT_STREQ("A B C", rest.c_str());
298
299 ASSERT_TRUE(tokenize_first(" A B C ", ' ', &token, &rest));
300 ASSERT_STREQ("", token.c_str());
301 ASSERT_STREQ("A B C ", rest.c_str());
302}
303
304TEST(TokenizeFirstTest, SingleToken) {
305 std::string token;
306 std::string rest;
307
308 // In the case where we cannot find delimiter the whole string is a token.
309 ASSERT_FALSE(tokenize_first("ABC", ' ', &token, &rest));
310
311 ASSERT_TRUE(tokenize_first("ABC ", ' ', &token, &rest));
312 ASSERT_STREQ("ABC", token.c_str());
313 ASSERT_STREQ("", rest.c_str());
314
315 ASSERT_TRUE(tokenize_first(" ABC ", ' ', &token, &rest));
316 ASSERT_STREQ("", token.c_str());
317 ASSERT_STREQ("ABC ", rest.c_str());
318}
319
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000320// Tests counting substrings.
321TEST(SplitTest, CountSubstrings) {
322 std::vector<std::string> fields;
323
324 EXPECT_EQ(5ul, split("one,two,three,four,five", ',', &fields));
325 fields.clear();
326 EXPECT_EQ(1ul, split("one", ',', &fields));
327
328 // Empty fields between commas count.
329 fields.clear();
330 EXPECT_EQ(5ul, split("one,,three,four,five", ',', &fields));
331 fields.clear();
332 EXPECT_EQ(3ul, split(",three,", ',', &fields));
333 fields.clear();
334 EXPECT_EQ(1ul, split("", ',', &fields));
335}
336
337// Tests comparing substrings.
338TEST(SplitTest, CompareSubstrings) {
339 std::vector<std::string> fields;
340
341 split("find,middle,one", ',', &fields);
342 ASSERT_EQ(3ul, fields.size());
343 ASSERT_STREQ("middle", fields.at(1).c_str());
344 fields.clear();
345
346 // Empty fields between commas count.
347 split("find,,middle,one", ',', &fields);
348 ASSERT_EQ(4ul, fields.size());
349 ASSERT_STREQ("middle", fields.at(2).c_str());
350 fields.clear();
351 split("", ',', &fields);
352 ASSERT_EQ(1ul, fields.size());
353 ASSERT_STREQ("", fields.at(0).c_str());
354}
355
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200356TEST(ToString, SanityCheck) {
357 EXPECT_EQ(ToString(true), "true");
358 EXPECT_EQ(ToString(false), "false");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000359
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200360 const char* c = "message";
361 EXPECT_EQ(ToString(c), c);
362 EXPECT_EQ(ToString(std::string(c)), c);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000363
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200364 EXPECT_EQ(ToString(short{-123}), "-123");
365 EXPECT_EQ(ToString((unsigned short)123), "123");
366 EXPECT_EQ(ToString(int{-123}), "-123");
367 EXPECT_EQ(ToString((unsigned int)123), "123");
368 EXPECT_EQ(ToString((long int)-123), "-123");
369 EXPECT_EQ(ToString((unsigned long int)123), "123");
370 EXPECT_EQ(ToString((long long int)-123), "-123");
371 EXPECT_EQ(ToString((unsigned long long int)123), "123");
372
373 int i = 10;
374 int* p = &i;
375 std::ostringstream s; // no-presubmit-check TODO(webrtc:8982)
376 s << p;
377 EXPECT_EQ(s.str(), ToString(p));
378
379 EXPECT_EQ(ToString(0.5), "0.5");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000380}
381
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200382template <typename T>
383void ParsesTo(std::string s, T t) {
384 T value;
385 EXPECT_TRUE(FromString(s, &value));
386 EXPECT_EQ(value, t);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000387}
388
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200389TEST(FromString, DecodeValid) {
390 ParsesTo("true", true);
391 ParsesTo("false", false);
392
393 ParsesTo("105", 105);
394 ParsesTo("0.25", 0.25);
395}
396
397template <typename T>
398void FailsToParse(std::string s) {
399 T value;
400 EXPECT_FALSE(FromString(s, &value)) << "[" << s << "]";
401}
402
403TEST(FromString, DecodeInvalid) {
404 FailsToParse<bool>("True");
405 FailsToParse<bool>("0");
406 FailsToParse<bool>("yes");
407
408 FailsToParse<int>("0.5");
409 FailsToParse<int>("XIV");
410 FailsToParse<double>("");
411 FailsToParse<double>(" ");
412 FailsToParse<int>("1 2");
413}
414
415template <typename T>
416void RoundTrip(T t) {
417 std::string s = ToString(t);
418 T value;
419 EXPECT_TRUE(FromString(s, &value));
420 EXPECT_EQ(value, t);
421}
422
423TEST(FromString, RoundTrip) {
424 RoundTrip<int>(123);
425 RoundTrip(false);
426 RoundTrip(true);
427 RoundTrip(0.5);
428 RoundTrip(-15l);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000429}
deadbeef0a6c4ca2015-10-06 11:38:28 -0700430
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000431} // namespace rtc