• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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