blob: ab871a5ce92f4b827a5661c1db967273bd2a98ab [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:261/*
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 04:47:3111#include "rtc_base/stringencode.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2612
Yves Gerey3e707812018-11-28 15:47:4913#include <string.h>
Jonas Olsson6b1985d2018-07-05 09:59:4814#include <sstream> // no-presubmit-check TODO(webrtc:8982)
15
Yves Gerey3e707812018-11-28 15:47:4916#include "test/gtest.h"
17
henrike@webrtc.orgf0488722014-05-13 18:00:2618namespace rtc {
19
henrike@webrtc.orgf0488722014-05-13 18:00:2620class 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 13:03:0548 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(encoded_), data_,
49 sizeof(data_), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:2650 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 13:03:0552 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), encoded_,
53 enc_res_, ':');
henrike@webrtc.orgf0488722014-05-13 18:00:2654 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 13:03:0560 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(encoded_), data_,
61 sizeof(data_), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:2662 ASSERT_EQ(sizeof(data_) * 3 - 1, enc_res_);
Yves Gerey665174f2018-06-19 13:03:0563 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), encoded_,
64 enc_res_, '/');
henrike@webrtc.orgf0488722014-05-13 18:00:2665 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 13:03:0572 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), encoded_,
73 enc_res_, ':');
henrike@webrtc.orgf0488722014-05-13 18:00:2674 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 13:03:0579 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(encoded_), data_,
80 sizeof(data_), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:2681 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 13:03:0598 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), encoded_,
99 enc_res_, ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26100 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 13:03:05123 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(data_) * 2, data_,
124 sizeof(data_), 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26125 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 13:03:05130 enc_res_ = hex_encode_with_delimiter(encoded_, sizeof(data_) * 3 - 1, data_,
131 sizeof(data_), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26132 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) {
Niels Möller12048c72018-10-29 11:58:48144 dec_res_ =
145 hex_decode_with_delimiter(decoded_, sizeof(decoded_), "axyz", 4, 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26146 ASSERT_EQ(0U, dec_res_);
147}
148
149// Test that decoding an odd number of hex characters fails.
150TEST_F(HexEncodeTest, TestDecodeOddHexDigits) {
151 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), "012", 3, 0);
152 ASSERT_EQ(0U, dec_res_);
153}
154
155// Test that decoding a string with too many delimiters fails.
156TEST_F(HexEncodeTest, TestDecodeWithDelimiterTooManyDelimiters) {
157 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "01::23::45::67", 14, ':');
158 ASSERT_EQ(0U, dec_res_);
159}
160
161// Test that decoding a string with a leading delimiter fails.
162TEST_F(HexEncodeTest, TestDecodeWithDelimiterLeadingDelimiter) {
163 dec_res_ = hex_decode_with_delimiter(decoded_, 4, ":01:23:45:67", 12, ':');
164 ASSERT_EQ(0U, dec_res_);
165}
166
167// Test that decoding a string with a trailing delimiter fails.
168TEST_F(HexEncodeTest, TestDecodeWithDelimiterTrailingDelimiter) {
169 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "01:23:45:67:", 12, ':');
170 ASSERT_EQ(0U, dec_res_);
171}
172
173// Tests counting substrings.
174TEST(TokenizeTest, CountSubstrings) {
175 std::vector<std::string> fields;
176
177 EXPECT_EQ(5ul, tokenize("one two three four five", ' ', &fields));
178 fields.clear();
179 EXPECT_EQ(1ul, tokenize("one", ' ', &fields));
180
181 // Extra spaces should be ignored.
182 fields.clear();
183 EXPECT_EQ(5ul, tokenize(" one two three four five ", ' ', &fields));
184 fields.clear();
185 EXPECT_EQ(1ul, tokenize(" one ", ' ', &fields));
186 fields.clear();
187 EXPECT_EQ(0ul, tokenize(" ", ' ', &fields));
188}
189
190// Tests comparing substrings.
191TEST(TokenizeTest, CompareSubstrings) {
192 std::vector<std::string> fields;
193
194 tokenize("find middle one", ' ', &fields);
195 ASSERT_EQ(3ul, fields.size());
196 ASSERT_STREQ("middle", fields.at(1).c_str());
197 fields.clear();
198
199 // Extra spaces should be ignored.
200 tokenize(" find middle one ", ' ', &fields);
201 ASSERT_EQ(3ul, fields.size());
202 ASSERT_STREQ("middle", fields.at(1).c_str());
203 fields.clear();
204 tokenize(" ", ' ', &fields);
205 ASSERT_EQ(0ul, fields.size());
206}
207
208TEST(TokenizeTest, TokenizeAppend) {
deadbeef37f5ecf2017-02-27 22:06:41209 ASSERT_EQ(0ul, tokenize_append("A B C", ' ', nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26210
211 std::vector<std::string> fields;
212
213 tokenize_append("A B C", ' ', &fields);
214 ASSERT_EQ(3ul, fields.size());
215 ASSERT_STREQ("B", fields.at(1).c_str());
216
217 tokenize_append("D E", ' ', &fields);
218 ASSERT_EQ(5ul, fields.size());
219 ASSERT_STREQ("B", fields.at(1).c_str());
220 ASSERT_STREQ("E", fields.at(4).c_str());
221}
222
223TEST(TokenizeTest, TokenizeWithMarks) {
deadbeef37f5ecf2017-02-27 22:06:41224 ASSERT_EQ(0ul, tokenize("D \"A B", ' ', '(', ')', nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26225
226 std::vector<std::string> fields;
227 tokenize("A B C", ' ', '"', '"', &fields);
228 ASSERT_EQ(3ul, fields.size());
229 ASSERT_STREQ("C", fields.at(2).c_str());
230
231 tokenize("\"A B\" C", ' ', '"', '"', &fields);
232 ASSERT_EQ(2ul, fields.size());
233 ASSERT_STREQ("A B", fields.at(0).c_str());
234
235 tokenize("D \"A B\" C", ' ', '"', '"', &fields);
236 ASSERT_EQ(3ul, fields.size());
237 ASSERT_STREQ("D", fields.at(0).c_str());
238 ASSERT_STREQ("A B", fields.at(1).c_str());
239
240 tokenize("D \"A B\" C \"E F\"", ' ', '"', '"', &fields);
241 ASSERT_EQ(4ul, fields.size());
242 ASSERT_STREQ("D", fields.at(0).c_str());
243 ASSERT_STREQ("A B", fields.at(1).c_str());
244 ASSERT_STREQ("E F", fields.at(3).c_str());
245
246 // No matching marks.
247 tokenize("D \"A B", ' ', '"', '"', &fields);
248 ASSERT_EQ(3ul, fields.size());
249 ASSERT_STREQ("D", fields.at(0).c_str());
250 ASSERT_STREQ("\"A", fields.at(1).c_str());
251
252 tokenize("D (A B) C (E F) G", ' ', '(', ')', &fields);
253 ASSERT_EQ(5ul, fields.size());
254 ASSERT_STREQ("D", fields.at(0).c_str());
255 ASSERT_STREQ("A B", fields.at(1).c_str());
256 ASSERT_STREQ("E F", fields.at(3).c_str());
257}
258
deadbeef0a6c4ca2015-10-06 18:38:28259TEST(TokenizeTest, TokenizeWithEmptyTokens) {
260 std::vector<std::string> fields;
261 EXPECT_EQ(3ul, tokenize_with_empty_tokens("a.b.c", '.', &fields));
262 EXPECT_EQ("a", fields[0]);
263 EXPECT_EQ("b", fields[1]);
264 EXPECT_EQ("c", fields[2]);
265
266 EXPECT_EQ(3ul, tokenize_with_empty_tokens("..c", '.', &fields));
267 EXPECT_TRUE(fields[0].empty());
268 EXPECT_TRUE(fields[1].empty());
269 EXPECT_EQ("c", fields[2]);
270
271 EXPECT_EQ(1ul, tokenize_with_empty_tokens("", '.', &fields));
272 EXPECT_TRUE(fields[0].empty());
273}
274
Donald Curtis0e07f922015-05-15 16:21:23275TEST(TokenizeFirstTest, NoLeadingSpaces) {
276 std::string token;
277 std::string rest;
278
279 ASSERT_TRUE(tokenize_first("A &*${}", ' ', &token, &rest));
280 ASSERT_STREQ("A", token.c_str());
281 ASSERT_STREQ("&*${}", rest.c_str());
282
283 ASSERT_TRUE(tokenize_first("A B& *${}", ' ', &token, &rest));
284 ASSERT_STREQ("A", token.c_str());
285 ASSERT_STREQ("B& *${}", rest.c_str());
286
287 ASSERT_TRUE(tokenize_first("A B& *${} ", ' ', &token, &rest));
288 ASSERT_STREQ("A", token.c_str());
289 ASSERT_STREQ("B& *${} ", rest.c_str());
290}
291
292TEST(TokenizeFirstTest, LeadingSpaces) {
293 std::string token;
294 std::string rest;
295
296 ASSERT_TRUE(tokenize_first(" A B C", ' ', &token, &rest));
297 ASSERT_STREQ("", token.c_str());
298 ASSERT_STREQ("A B C", rest.c_str());
299
300 ASSERT_TRUE(tokenize_first(" A B C ", ' ', &token, &rest));
301 ASSERT_STREQ("", token.c_str());
302 ASSERT_STREQ("A B C ", rest.c_str());
303}
304
305TEST(TokenizeFirstTest, SingleToken) {
306 std::string token;
307 std::string rest;
308
309 // In the case where we cannot find delimiter the whole string is a token.
310 ASSERT_FALSE(tokenize_first("ABC", ' ', &token, &rest));
311
312 ASSERT_TRUE(tokenize_first("ABC ", ' ', &token, &rest));
313 ASSERT_STREQ("ABC", token.c_str());
314 ASSERT_STREQ("", rest.c_str());
315
316 ASSERT_TRUE(tokenize_first(" ABC ", ' ', &token, &rest));
317 ASSERT_STREQ("", token.c_str());
318 ASSERT_STREQ("ABC ", rest.c_str());
319}
320
henrike@webrtc.orgf0488722014-05-13 18:00:26321// Tests counting substrings.
322TEST(SplitTest, CountSubstrings) {
323 std::vector<std::string> fields;
324
325 EXPECT_EQ(5ul, split("one,two,three,four,five", ',', &fields));
326 fields.clear();
327 EXPECT_EQ(1ul, split("one", ',', &fields));
328
329 // Empty fields between commas count.
330 fields.clear();
331 EXPECT_EQ(5ul, split("one,,three,four,five", ',', &fields));
332 fields.clear();
333 EXPECT_EQ(3ul, split(",three,", ',', &fields));
334 fields.clear();
335 EXPECT_EQ(1ul, split("", ',', &fields));
336}
337
338// Tests comparing substrings.
339TEST(SplitTest, CompareSubstrings) {
340 std::vector<std::string> fields;
341
342 split("find,middle,one", ',', &fields);
343 ASSERT_EQ(3ul, fields.size());
344 ASSERT_STREQ("middle", fields.at(1).c_str());
345 fields.clear();
346
347 // Empty fields between commas count.
348 split("find,,middle,one", ',', &fields);
349 ASSERT_EQ(4ul, fields.size());
350 ASSERT_STREQ("middle", fields.at(2).c_str());
351 fields.clear();
352 split("", ',', &fields);
353 ASSERT_EQ(1ul, fields.size());
354 ASSERT_STREQ("", fields.at(0).c_str());
355}
356
Jonas Olsson6b1985d2018-07-05 09:59:48357TEST(ToString, SanityCheck) {
358 EXPECT_EQ(ToString(true), "true");
359 EXPECT_EQ(ToString(false), "false");
henrike@webrtc.orgf0488722014-05-13 18:00:26360
Jonas Olsson6b1985d2018-07-05 09:59:48361 const char* c = "message";
362 EXPECT_EQ(ToString(c), c);
363 EXPECT_EQ(ToString(std::string(c)), c);
henrike@webrtc.orgf0488722014-05-13 18:00:26364
Jonas Olsson6b1985d2018-07-05 09:59:48365 EXPECT_EQ(ToString(short{-123}), "-123");
366 EXPECT_EQ(ToString((unsigned short)123), "123");
367 EXPECT_EQ(ToString(int{-123}), "-123");
368 EXPECT_EQ(ToString((unsigned int)123), "123");
369 EXPECT_EQ(ToString((long int)-123), "-123");
370 EXPECT_EQ(ToString((unsigned long int)123), "123");
371 EXPECT_EQ(ToString((long long int)-123), "-123");
372 EXPECT_EQ(ToString((unsigned long long int)123), "123");
373
374 int i = 10;
375 int* p = &i;
376 std::ostringstream s; // no-presubmit-check TODO(webrtc:8982)
377 s << p;
378 EXPECT_EQ(s.str(), ToString(p));
379
380 EXPECT_EQ(ToString(0.5), "0.5");
henrike@webrtc.orgf0488722014-05-13 18:00:26381}
382
Jonas Olsson6b1985d2018-07-05 09:59:48383template <typename T>
384void ParsesTo(std::string s, T t) {
385 T value;
386 EXPECT_TRUE(FromString(s, &value));
387 EXPECT_EQ(value, t);
henrike@webrtc.orgf0488722014-05-13 18:00:26388}
389
Jonas Olsson6b1985d2018-07-05 09:59:48390TEST(FromString, DecodeValid) {
391 ParsesTo("true", true);
392 ParsesTo("false", false);
393
394 ParsesTo("105", 105);
395 ParsesTo("0.25", 0.25);
396}
397
398template <typename T>
399void FailsToParse(std::string s) {
400 T value;
401 EXPECT_FALSE(FromString(s, &value)) << "[" << s << "]";
402}
403
404TEST(FromString, DecodeInvalid) {
405 FailsToParse<bool>("True");
406 FailsToParse<bool>("0");
407 FailsToParse<bool>("yes");
408
409 FailsToParse<int>("0.5");
410 FailsToParse<int>("XIV");
411 FailsToParse<double>("");
412 FailsToParse<double>(" ");
413 FailsToParse<int>("1 2");
414}
415
416template <typename T>
417void RoundTrip(T t) {
418 std::string s = ToString(t);
419 T value;
420 EXPECT_TRUE(FromString(s, &value));
421 EXPECT_EQ(value, t);
422}
423
424TEST(FromString, RoundTrip) {
425 RoundTrip<int>(123);
426 RoundTrip(false);
427 RoundTrip(true);
428 RoundTrip(0.5);
429 RoundTrip(-15l);
henrike@webrtc.orgf0488722014-05-13 18:00:26430}
deadbeef0a6c4ca2015-10-06 18:38:28431
henrike@webrtc.orgf0488722014-05-13 18:00:26432} // namespace rtc