blob: 485429950a79db35f2b706d44d9ec19aee1b02b7 [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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "rtc_base/string_encode.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
Jonas Olsson6b1985d2018-07-05 11:59:48 +020014#include <sstream> // no-presubmit-check TODO(webrtc:8982)
15
Yves Gerey3e707812018-11-28 16:47:49 +010016#include "test/gtest.h"
17
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000018namespace rtc {
19
Mirko Bonadei6a489f22019-04-09 15:11:12 +020020class HexEncodeTest : public ::testing::Test {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000021 public:
Niels Möllere7e36012019-05-23 12:10:26 +020022 HexEncodeTest() : dec_res_(0) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000023 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];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000030 char decoded_[11];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000031 size_t dec_res_;
32};
33
34// Test that we can convert to/from hex with no delimiter.
35TEST_F(HexEncodeTest, TestWithNoDelimiter) {
Niels Möllere7e36012019-05-23 12:10:26 +020036 std::string encoded = hex_encode(data_, sizeof(data_));
37 EXPECT_EQ("80818283848586878889", encoded);
38 dec_res_ =
39 hex_decode(decoded_, sizeof(decoded_), encoded.data(), encoded.size());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000040 ASSERT_EQ(sizeof(data_), dec_res_);
41 ASSERT_EQ(0, memcmp(data_, decoded_, dec_res_));
42}
43
44// Test that we can convert to/from hex with a colon delimiter.
45TEST_F(HexEncodeTest, TestWithDelimiter) {
Niels Möllere7e36012019-05-23 12:10:26 +020046 std::string encoded = hex_encode_with_delimiter(data_, sizeof(data_), ':');
47 EXPECT_EQ("80:81:82:83:84:85:86:87:88:89", encoded);
48 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
49 encoded.data(), encoded.size(), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000050 ASSERT_EQ(sizeof(data_), dec_res_);
51 ASSERT_EQ(0, memcmp(data_, decoded_, dec_res_));
52}
53
54// Test that encoding with one delimiter and decoding with another fails.
55TEST_F(HexEncodeTest, TestWithWrongDelimiter) {
Niels Möllere7e36012019-05-23 12:10:26 +020056 std::string encoded = hex_encode_with_delimiter(data_, sizeof(data_), ':');
57 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
58 encoded.data(), encoded.size(), '/');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000059 ASSERT_EQ(0U, dec_res_);
60}
61
62// Test that encoding without a delimiter and decoding with one fails.
63TEST_F(HexEncodeTest, TestExpectedDelimiter) {
Niels Möllere7e36012019-05-23 12:10:26 +020064 std::string encoded = hex_encode(data_, sizeof(data_));
65 EXPECT_EQ(sizeof(data_) * 2, encoded.size());
66 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
67 encoded.data(), encoded.size(), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000068 ASSERT_EQ(0U, dec_res_);
69}
70
71// Test that encoding with a delimiter and decoding without one fails.
72TEST_F(HexEncodeTest, TestExpectedNoDelimiter) {
Niels Möllere7e36012019-05-23 12:10:26 +020073 std::string encoded = hex_encode_with_delimiter(data_, sizeof(data_), ':');
74 EXPECT_EQ(sizeof(data_) * 3 - 1, encoded.size());
75 dec_res_ =
76 hex_decode(decoded_, sizeof(decoded_), encoded.data(), encoded.size());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000077 ASSERT_EQ(0U, dec_res_);
78}
79
80// Test that we handle a zero-length buffer with no delimiter.
81TEST_F(HexEncodeTest, TestZeroLengthNoDelimiter) {
Niels Möllere7e36012019-05-23 12:10:26 +020082 std::string encoded = hex_encode("", 0);
83 EXPECT_TRUE(encoded.empty());
84 dec_res_ =
85 hex_decode(decoded_, sizeof(decoded_), encoded.data(), encoded.size());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000086 ASSERT_EQ(0U, dec_res_);
87}
88
89// Test that we handle a zero-length buffer with a delimiter.
90TEST_F(HexEncodeTest, TestZeroLengthWithDelimiter) {
Niels Möllere7e36012019-05-23 12:10:26 +020091 std::string encoded = hex_encode_with_delimiter("", 0, ':');
92 EXPECT_TRUE(encoded.empty());
93 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
94 encoded.data(), encoded.size(), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000095 ASSERT_EQ(0U, dec_res_);
96}
97
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000098// Test that decoding into a too-small output buffer fails.
99TEST_F(HexEncodeTest, TestDecodeTooShort) {
100 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "0123456789", 10, 0);
101 ASSERT_EQ(0U, dec_res_);
102 ASSERT_EQ(0x7f, decoded_[4]);
103}
104
105// Test that decoding non-hex data fails.
106TEST_F(HexEncodeTest, TestDecodeBogusData) {
Niels Möller12048c72018-10-29 12:58:48 +0100107 dec_res_ =
108 hex_decode_with_delimiter(decoded_, sizeof(decoded_), "axyz", 4, 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000109 ASSERT_EQ(0U, dec_res_);
110}
111
112// Test that decoding an odd number of hex characters fails.
113TEST_F(HexEncodeTest, TestDecodeOddHexDigits) {
114 dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), "012", 3, 0);
115 ASSERT_EQ(0U, dec_res_);
116}
117
118// Test that decoding a string with too many delimiters fails.
119TEST_F(HexEncodeTest, TestDecodeWithDelimiterTooManyDelimiters) {
120 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "01::23::45::67", 14, ':');
121 ASSERT_EQ(0U, dec_res_);
122}
123
124// Test that decoding a string with a leading delimiter fails.
125TEST_F(HexEncodeTest, TestDecodeWithDelimiterLeadingDelimiter) {
126 dec_res_ = hex_decode_with_delimiter(decoded_, 4, ":01:23:45:67", 12, ':');
127 ASSERT_EQ(0U, dec_res_);
128}
129
130// Test that decoding a string with a trailing delimiter fails.
131TEST_F(HexEncodeTest, TestDecodeWithDelimiterTrailingDelimiter) {
132 dec_res_ = hex_decode_with_delimiter(decoded_, 4, "01:23:45:67:", 12, ':');
133 ASSERT_EQ(0U, dec_res_);
134}
135
136// Tests counting substrings.
137TEST(TokenizeTest, CountSubstrings) {
138 std::vector<std::string> fields;
139
140 EXPECT_EQ(5ul, tokenize("one two three four five", ' ', &fields));
141 fields.clear();
142 EXPECT_EQ(1ul, tokenize("one", ' ', &fields));
143
144 // Extra spaces should be ignored.
145 fields.clear();
146 EXPECT_EQ(5ul, tokenize(" one two three four five ", ' ', &fields));
147 fields.clear();
148 EXPECT_EQ(1ul, tokenize(" one ", ' ', &fields));
149 fields.clear();
150 EXPECT_EQ(0ul, tokenize(" ", ' ', &fields));
151}
152
153// Tests comparing substrings.
154TEST(TokenizeTest, CompareSubstrings) {
155 std::vector<std::string> fields;
156
157 tokenize("find middle one", ' ', &fields);
158 ASSERT_EQ(3ul, fields.size());
159 ASSERT_STREQ("middle", fields.at(1).c_str());
160 fields.clear();
161
162 // Extra spaces should be ignored.
163 tokenize(" find middle one ", ' ', &fields);
164 ASSERT_EQ(3ul, fields.size());
165 ASSERT_STREQ("middle", fields.at(1).c_str());
166 fields.clear();
167 tokenize(" ", ' ', &fields);
168 ASSERT_EQ(0ul, fields.size());
169}
170
171TEST(TokenizeTest, TokenizeAppend) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800172 ASSERT_EQ(0ul, tokenize_append("A B C", ' ', nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000173
174 std::vector<std::string> fields;
175
176 tokenize_append("A B C", ' ', &fields);
177 ASSERT_EQ(3ul, fields.size());
178 ASSERT_STREQ("B", fields.at(1).c_str());
179
180 tokenize_append("D E", ' ', &fields);
181 ASSERT_EQ(5ul, fields.size());
182 ASSERT_STREQ("B", fields.at(1).c_str());
183 ASSERT_STREQ("E", fields.at(4).c_str());
184}
185
186TEST(TokenizeTest, TokenizeWithMarks) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800187 ASSERT_EQ(0ul, tokenize("D \"A B", ' ', '(', ')', nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000188
189 std::vector<std::string> fields;
190 tokenize("A B C", ' ', '"', '"', &fields);
191 ASSERT_EQ(3ul, fields.size());
192 ASSERT_STREQ("C", fields.at(2).c_str());
193
194 tokenize("\"A B\" C", ' ', '"', '"', &fields);
195 ASSERT_EQ(2ul, fields.size());
196 ASSERT_STREQ("A B", fields.at(0).c_str());
197
198 tokenize("D \"A B\" C", ' ', '"', '"', &fields);
199 ASSERT_EQ(3ul, fields.size());
200 ASSERT_STREQ("D", fields.at(0).c_str());
201 ASSERT_STREQ("A B", fields.at(1).c_str());
202
203 tokenize("D \"A B\" C \"E F\"", ' ', '"', '"', &fields);
204 ASSERT_EQ(4ul, fields.size());
205 ASSERT_STREQ("D", fields.at(0).c_str());
206 ASSERT_STREQ("A B", fields.at(1).c_str());
207 ASSERT_STREQ("E F", fields.at(3).c_str());
208
209 // No matching marks.
210 tokenize("D \"A B", ' ', '"', '"', &fields);
211 ASSERT_EQ(3ul, fields.size());
212 ASSERT_STREQ("D", fields.at(0).c_str());
213 ASSERT_STREQ("\"A", fields.at(1).c_str());
214
215 tokenize("D (A B) C (E F) G", ' ', '(', ')', &fields);
216 ASSERT_EQ(5ul, fields.size());
217 ASSERT_STREQ("D", fields.at(0).c_str());
218 ASSERT_STREQ("A B", fields.at(1).c_str());
219 ASSERT_STREQ("E F", fields.at(3).c_str());
220}
221
deadbeef0a6c4ca2015-10-06 11:38:28 -0700222TEST(TokenizeTest, TokenizeWithEmptyTokens) {
223 std::vector<std::string> fields;
224 EXPECT_EQ(3ul, tokenize_with_empty_tokens("a.b.c", '.', &fields));
225 EXPECT_EQ("a", fields[0]);
226 EXPECT_EQ("b", fields[1]);
227 EXPECT_EQ("c", fields[2]);
228
229 EXPECT_EQ(3ul, tokenize_with_empty_tokens("..c", '.', &fields));
230 EXPECT_TRUE(fields[0].empty());
231 EXPECT_TRUE(fields[1].empty());
232 EXPECT_EQ("c", fields[2]);
233
234 EXPECT_EQ(1ul, tokenize_with_empty_tokens("", '.', &fields));
235 EXPECT_TRUE(fields[0].empty());
236}
237
Donald Curtis0e07f922015-05-15 09:21:23 -0700238TEST(TokenizeFirstTest, NoLeadingSpaces) {
239 std::string token;
240 std::string rest;
241
242 ASSERT_TRUE(tokenize_first("A &*${}", ' ', &token, &rest));
243 ASSERT_STREQ("A", token.c_str());
244 ASSERT_STREQ("&*${}", rest.c_str());
245
246 ASSERT_TRUE(tokenize_first("A B& *${}", ' ', &token, &rest));
247 ASSERT_STREQ("A", token.c_str());
248 ASSERT_STREQ("B& *${}", rest.c_str());
249
250 ASSERT_TRUE(tokenize_first("A B& *${} ", ' ', &token, &rest));
251 ASSERT_STREQ("A", token.c_str());
252 ASSERT_STREQ("B& *${} ", rest.c_str());
253}
254
255TEST(TokenizeFirstTest, LeadingSpaces) {
256 std::string token;
257 std::string rest;
258
259 ASSERT_TRUE(tokenize_first(" A B C", ' ', &token, &rest));
260 ASSERT_STREQ("", token.c_str());
261 ASSERT_STREQ("A B C", rest.c_str());
262
263 ASSERT_TRUE(tokenize_first(" A B C ", ' ', &token, &rest));
264 ASSERT_STREQ("", token.c_str());
265 ASSERT_STREQ("A B C ", rest.c_str());
266}
267
268TEST(TokenizeFirstTest, SingleToken) {
269 std::string token;
270 std::string rest;
271
272 // In the case where we cannot find delimiter the whole string is a token.
273 ASSERT_FALSE(tokenize_first("ABC", ' ', &token, &rest));
274
275 ASSERT_TRUE(tokenize_first("ABC ", ' ', &token, &rest));
276 ASSERT_STREQ("ABC", token.c_str());
277 ASSERT_STREQ("", rest.c_str());
278
279 ASSERT_TRUE(tokenize_first(" ABC ", ' ', &token, &rest));
280 ASSERT_STREQ("", token.c_str());
281 ASSERT_STREQ("ABC ", rest.c_str());
282}
283
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000284// Tests counting substrings.
285TEST(SplitTest, CountSubstrings) {
286 std::vector<std::string> fields;
287
288 EXPECT_EQ(5ul, split("one,two,three,four,five", ',', &fields));
289 fields.clear();
290 EXPECT_EQ(1ul, split("one", ',', &fields));
291
292 // Empty fields between commas count.
293 fields.clear();
294 EXPECT_EQ(5ul, split("one,,three,four,five", ',', &fields));
295 fields.clear();
296 EXPECT_EQ(3ul, split(",three,", ',', &fields));
297 fields.clear();
298 EXPECT_EQ(1ul, split("", ',', &fields));
299}
300
301// Tests comparing substrings.
302TEST(SplitTest, CompareSubstrings) {
303 std::vector<std::string> fields;
304
305 split("find,middle,one", ',', &fields);
306 ASSERT_EQ(3ul, fields.size());
307 ASSERT_STREQ("middle", fields.at(1).c_str());
308 fields.clear();
309
310 // Empty fields between commas count.
311 split("find,,middle,one", ',', &fields);
312 ASSERT_EQ(4ul, fields.size());
313 ASSERT_STREQ("middle", fields.at(2).c_str());
314 fields.clear();
315 split("", ',', &fields);
316 ASSERT_EQ(1ul, fields.size());
317 ASSERT_STREQ("", fields.at(0).c_str());
318}
319
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200320TEST(ToString, SanityCheck) {
321 EXPECT_EQ(ToString(true), "true");
322 EXPECT_EQ(ToString(false), "false");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000323
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200324 const char* c = "message";
325 EXPECT_EQ(ToString(c), c);
326 EXPECT_EQ(ToString(std::string(c)), c);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000327
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200328 EXPECT_EQ(ToString(short{-123}), "-123");
329 EXPECT_EQ(ToString((unsigned short)123), "123");
330 EXPECT_EQ(ToString(int{-123}), "-123");
331 EXPECT_EQ(ToString((unsigned int)123), "123");
332 EXPECT_EQ(ToString((long int)-123), "-123");
333 EXPECT_EQ(ToString((unsigned long int)123), "123");
334 EXPECT_EQ(ToString((long long int)-123), "-123");
335 EXPECT_EQ(ToString((unsigned long long int)123), "123");
336
337 int i = 10;
338 int* p = &i;
339 std::ostringstream s; // no-presubmit-check TODO(webrtc:8982)
340 s << p;
341 EXPECT_EQ(s.str(), ToString(p));
342
343 EXPECT_EQ(ToString(0.5), "0.5");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000344}
345
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200346template <typename T>
347void ParsesTo(std::string s, T t) {
348 T value;
349 EXPECT_TRUE(FromString(s, &value));
350 EXPECT_EQ(value, t);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000351}
352
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200353TEST(FromString, DecodeValid) {
354 ParsesTo("true", true);
355 ParsesTo("false", false);
356
357 ParsesTo("105", 105);
358 ParsesTo("0.25", 0.25);
359}
360
361template <typename T>
362void FailsToParse(std::string s) {
363 T value;
364 EXPECT_FALSE(FromString(s, &value)) << "[" << s << "]";
365}
366
367TEST(FromString, DecodeInvalid) {
368 FailsToParse<bool>("True");
369 FailsToParse<bool>("0");
370 FailsToParse<bool>("yes");
371
372 FailsToParse<int>("0.5");
373 FailsToParse<int>("XIV");
374 FailsToParse<double>("");
375 FailsToParse<double>(" ");
376 FailsToParse<int>("1 2");
377}
378
379template <typename T>
380void RoundTrip(T t) {
381 std::string s = ToString(t);
382 T value;
383 EXPECT_TRUE(FromString(s, &value));
384 EXPECT_EQ(value, t);
385}
386
387TEST(FromString, RoundTrip) {
388 RoundTrip<int>(123);
389 RoundTrip(false);
390 RoundTrip(true);
391 RoundTrip(0.5);
392 RoundTrip(-15l);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000393}
deadbeef0a6c4ca2015-10-06 11:38:28 -0700394
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000395} // namespace rtc