blob: 93453c328500d7c60afb0bbff33e97fffeedf26b [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
Steve Anton10542f22019-01-11 17:11:0011#include "rtc_base/string_encode.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2612
Yves Gerey3e707812018-11-28 15:47:4913#include <string.h>
Jonas Olssona4d87372019-07-05 17:08:3314
Ali Tofighfd6a4d62022-03-31 08:36:4815#include "api/array_view.h"
Tommi187a4362024-07-09 08:29:4416#include "rtc_base/strings/string_format.h"
Yves Gerey3e707812018-11-28 15:47:4917#include "test/gtest.h"
18
henrike@webrtc.orgf0488722014-05-13 18:00:2619namespace rtc {
20
Mirko Bonadei6a489f22019-04-09 13:11:1221class HexEncodeTest : public ::testing::Test {
henrike@webrtc.orgf0488722014-05-13 18:00:2622 public:
Niels Möllere7e36012019-05-23 10:10:2623 HexEncodeTest() : dec_res_(0) {
henrike@webrtc.orgf0488722014-05-13 18:00:2624 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];
Ali Tofighfd6a4d62022-03-31 08:36:4831 absl::string_view data_view_{data_, sizeof(data_)};
henrike@webrtc.orgf0488722014-05-13 18:00:2632 char decoded_[11];
henrike@webrtc.orgf0488722014-05-13 18:00:2633 size_t dec_res_;
34};
35
36// Test that we can convert to/from hex with no delimiter.
37TEST_F(HexEncodeTest, TestWithNoDelimiter) {
Ali Tofighfd6a4d62022-03-31 08:36:4838 std::string encoded = hex_encode(data_view_);
Niels Möllere7e36012019-05-23 10:10:2639 EXPECT_EQ("80818283848586878889", encoded);
Ali Tofighfd6a4d62022-03-31 08:36:4840 dec_res_ = hex_decode(ArrayView<char>(decoded_), encoded);
henrike@webrtc.orgf0488722014-05-13 18:00:2641 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.
46TEST_F(HexEncodeTest, TestWithDelimiter) {
Ali Tofighfd6a4d62022-03-31 08:36:4847 std::string encoded = hex_encode_with_delimiter(data_view_, ':');
Niels Möllere7e36012019-05-23 10:10:2648 EXPECT_EQ("80:81:82:83:84:85:86:87:88:89", encoded);
Ali Tofighfd6a4d62022-03-31 08:36:4849 dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), encoded, ':');
henrike@webrtc.orgf0488722014-05-13 18:00:2650 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) {
Ali Tofighfd6a4d62022-03-31 08:36:4856 std::string encoded = hex_encode_with_delimiter(data_view_, ':');
57 dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), encoded, '/');
henrike@webrtc.orgf0488722014-05-13 18:00:2658 ASSERT_EQ(0U, dec_res_);
59}
60
61// Test that encoding without a delimiter and decoding with one fails.
62TEST_F(HexEncodeTest, TestExpectedDelimiter) {
Ali Tofighfd6a4d62022-03-31 08:36:4863 std::string encoded = hex_encode(data_view_);
Niels Möllere7e36012019-05-23 10:10:2664 EXPECT_EQ(sizeof(data_) * 2, encoded.size());
Ali Tofighfd6a4d62022-03-31 08:36:4865 dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), encoded, ':');
henrike@webrtc.orgf0488722014-05-13 18:00:2666 ASSERT_EQ(0U, dec_res_);
67}
68
69// Test that encoding with a delimiter and decoding without one fails.
70TEST_F(HexEncodeTest, TestExpectedNoDelimiter) {
Ali Tofighfd6a4d62022-03-31 08:36:4871 std::string encoded = hex_encode_with_delimiter(data_view_, ':');
Niels Möllere7e36012019-05-23 10:10:2672 EXPECT_EQ(sizeof(data_) * 3 - 1, encoded.size());
Ali Tofighfd6a4d62022-03-31 08:36:4873 dec_res_ = hex_decode(ArrayView<char>(decoded_), encoded);
henrike@webrtc.orgf0488722014-05-13 18:00:2674 ASSERT_EQ(0U, dec_res_);
75}
76
77// Test that we handle a zero-length buffer with no delimiter.
78TEST_F(HexEncodeTest, TestZeroLengthNoDelimiter) {
Ali Tofighfd6a4d62022-03-31 08:36:4879 std::string encoded = hex_encode("");
Niels Möllere7e36012019-05-23 10:10:2680 EXPECT_TRUE(encoded.empty());
Ali Tofighfd6a4d62022-03-31 08:36:4881 dec_res_ = hex_decode(ArrayView<char>(decoded_), encoded);
henrike@webrtc.orgf0488722014-05-13 18:00:2682 ASSERT_EQ(0U, dec_res_);
83}
84
85// Test that we handle a zero-length buffer with a delimiter.
86TEST_F(HexEncodeTest, TestZeroLengthWithDelimiter) {
Ali Tofighfd6a4d62022-03-31 08:36:4887 std::string encoded = hex_encode_with_delimiter("", ':');
Niels Möllere7e36012019-05-23 10:10:2688 EXPECT_TRUE(encoded.empty());
Ali Tofighfd6a4d62022-03-31 08:36:4889 dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), encoded, ':');
henrike@webrtc.orgf0488722014-05-13 18:00:2690 ASSERT_EQ(0U, dec_res_);
91}
92
henrike@webrtc.orgf0488722014-05-13 18:00:2693// Test that decoding into a too-small output buffer fails.
94TEST_F(HexEncodeTest, TestDecodeTooShort) {
Ali Tofighfd6a4d62022-03-31 08:36:4895 dec_res_ =
96 hex_decode_with_delimiter(ArrayView<char>(decoded_, 4), "0123456789", 0);
henrike@webrtc.orgf0488722014-05-13 18:00:2697 ASSERT_EQ(0U, dec_res_);
98 ASSERT_EQ(0x7f, decoded_[4]);
99}
100
101// Test that decoding non-hex data fails.
102TEST_F(HexEncodeTest, TestDecodeBogusData) {
Ali Tofighfd6a4d62022-03-31 08:36:48103 dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), "axyz", 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26104 ASSERT_EQ(0U, dec_res_);
105}
106
107// Test that decoding an odd number of hex characters fails.
108TEST_F(HexEncodeTest, TestDecodeOddHexDigits) {
Ali Tofighfd6a4d62022-03-31 08:36:48109 dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), "012", 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26110 ASSERT_EQ(0U, dec_res_);
111}
112
113// Test that decoding a string with too many delimiters fails.
114TEST_F(HexEncodeTest, TestDecodeWithDelimiterTooManyDelimiters) {
Ali Tofighfd6a4d62022-03-31 08:36:48115 dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_, 4),
116 "01::23::45::67", ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26117 ASSERT_EQ(0U, dec_res_);
118}
119
120// Test that decoding a string with a leading delimiter fails.
121TEST_F(HexEncodeTest, TestDecodeWithDelimiterLeadingDelimiter) {
Ali Tofighfd6a4d62022-03-31 08:36:48122 dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_, 4),
123 ":01:23:45:67", ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26124 ASSERT_EQ(0U, dec_res_);
125}
126
127// Test that decoding a string with a trailing delimiter fails.
128TEST_F(HexEncodeTest, TestDecodeWithDelimiterTrailingDelimiter) {
Ali Tofighfd6a4d62022-03-31 08:36:48129 dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_, 4),
130 "01:23:45:67:", ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26131 ASSERT_EQ(0U, dec_res_);
132}
133
134// Tests counting substrings.
135TEST(TokenizeTest, CountSubstrings) {
136 std::vector<std::string> fields;
137
138 EXPECT_EQ(5ul, tokenize("one two three four five", ' ', &fields));
139 fields.clear();
140 EXPECT_EQ(1ul, tokenize("one", ' ', &fields));
141
142 // Extra spaces should be ignored.
143 fields.clear();
144 EXPECT_EQ(5ul, tokenize(" one two three four five ", ' ', &fields));
145 fields.clear();
146 EXPECT_EQ(1ul, tokenize(" one ", ' ', &fields));
147 fields.clear();
148 EXPECT_EQ(0ul, tokenize(" ", ' ', &fields));
149}
150
151// Tests comparing substrings.
152TEST(TokenizeTest, CompareSubstrings) {
153 std::vector<std::string> fields;
154
155 tokenize("find middle one", ' ', &fields);
156 ASSERT_EQ(3ul, fields.size());
157 ASSERT_STREQ("middle", fields.at(1).c_str());
158 fields.clear();
159
160 // Extra spaces should be ignored.
161 tokenize(" find middle one ", ' ', &fields);
162 ASSERT_EQ(3ul, fields.size());
163 ASSERT_STREQ("middle", fields.at(1).c_str());
164 fields.clear();
165 tokenize(" ", ' ', &fields);
166 ASSERT_EQ(0ul, fields.size());
167}
168
Donald Curtis0e07f922015-05-15 16:21:23169TEST(TokenizeFirstTest, NoLeadingSpaces) {
170 std::string token;
171 std::string rest;
172
173 ASSERT_TRUE(tokenize_first("A &*${}", ' ', &token, &rest));
174 ASSERT_STREQ("A", token.c_str());
175 ASSERT_STREQ("&*${}", rest.c_str());
176
177 ASSERT_TRUE(tokenize_first("A B& *${}", ' ', &token, &rest));
178 ASSERT_STREQ("A", token.c_str());
179 ASSERT_STREQ("B& *${}", rest.c_str());
180
181 ASSERT_TRUE(tokenize_first("A B& *${} ", ' ', &token, &rest));
182 ASSERT_STREQ("A", token.c_str());
183 ASSERT_STREQ("B& *${} ", rest.c_str());
184}
185
186TEST(TokenizeFirstTest, LeadingSpaces) {
187 std::string token;
188 std::string rest;
189
190 ASSERT_TRUE(tokenize_first(" A B C", ' ', &token, &rest));
191 ASSERT_STREQ("", token.c_str());
192 ASSERT_STREQ("A B C", rest.c_str());
193
194 ASSERT_TRUE(tokenize_first(" A B C ", ' ', &token, &rest));
195 ASSERT_STREQ("", token.c_str());
196 ASSERT_STREQ("A B C ", rest.c_str());
197}
198
199TEST(TokenizeFirstTest, SingleToken) {
200 std::string token;
201 std::string rest;
202
203 // In the case where we cannot find delimiter the whole string is a token.
204 ASSERT_FALSE(tokenize_first("ABC", ' ', &token, &rest));
205
206 ASSERT_TRUE(tokenize_first("ABC ", ' ', &token, &rest));
207 ASSERT_STREQ("ABC", token.c_str());
208 ASSERT_STREQ("", rest.c_str());
209
210 ASSERT_TRUE(tokenize_first(" ABC ", ' ', &token, &rest));
211 ASSERT_STREQ("", token.c_str());
212 ASSERT_STREQ("ABC ", rest.c_str());
213}
214
henrike@webrtc.orgf0488722014-05-13 18:00:26215// Tests counting substrings.
216TEST(SplitTest, CountSubstrings) {
Niels Möllerf1d822b2022-06-07 11:58:27217 EXPECT_EQ(5ul, split("one,two,three,four,five", ',').size());
218 EXPECT_EQ(1ul, split("one", ',').size());
henrike@webrtc.orgf0488722014-05-13 18:00:26219
220 // Empty fields between commas count.
Niels Möllerf1d822b2022-06-07 11:58:27221 EXPECT_EQ(5ul, split("one,,three,four,five", ',').size());
222 EXPECT_EQ(3ul, split(",three,", ',').size());
223 EXPECT_EQ(1ul, split("", ',').size());
henrike@webrtc.orgf0488722014-05-13 18:00:26224}
225
226// Tests comparing substrings.
227TEST(SplitTest, CompareSubstrings) {
Niels Möllerf1d822b2022-06-07 11:58:27228 std::vector<absl::string_view> fields = split("find,middle,one", ',');
henrike@webrtc.orgf0488722014-05-13 18:00:26229 ASSERT_EQ(3ul, fields.size());
Niels Möllerf1d822b2022-06-07 11:58:27230 ASSERT_EQ("middle", fields.at(1));
henrike@webrtc.orgf0488722014-05-13 18:00:26231
232 // Empty fields between commas count.
Niels Möllerf1d822b2022-06-07 11:58:27233 fields = split("find,,middle,one", ',');
henrike@webrtc.orgf0488722014-05-13 18:00:26234 ASSERT_EQ(4ul, fields.size());
Niels Möllerf1d822b2022-06-07 11:58:27235 ASSERT_EQ("middle", fields.at(2));
236 fields = split("", ',');
henrike@webrtc.orgf0488722014-05-13 18:00:26237 ASSERT_EQ(1ul, fields.size());
Niels Möllerf1d822b2022-06-07 11:58:27238 ASSERT_EQ("", fields.at(0));
henrike@webrtc.orgf0488722014-05-13 18:00:26239}
240
Niels Möller634f2792021-09-07 14:06:57241TEST(SplitTest, EmptyTokens) {
Niels Möllerf1d822b2022-06-07 11:58:27242 std::vector<absl::string_view> fields = split("a.b.c", '.');
243 ASSERT_EQ(3ul, fields.size());
Niels Möller634f2792021-09-07 14:06:57244 EXPECT_EQ("a", fields[0]);
245 EXPECT_EQ("b", fields[1]);
246 EXPECT_EQ("c", fields[2]);
247
Niels Möllerf1d822b2022-06-07 11:58:27248 fields = split("..c", '.');
249 ASSERT_EQ(3ul, fields.size());
Niels Möller634f2792021-09-07 14:06:57250 EXPECT_TRUE(fields[0].empty());
251 EXPECT_TRUE(fields[1].empty());
252 EXPECT_EQ("c", fields[2]);
253
Niels Möllerf1d822b2022-06-07 11:58:27254 fields = split("", '.');
255 ASSERT_EQ(1ul, fields.size());
Niels Möller634f2792021-09-07 14:06:57256 EXPECT_TRUE(fields[0].empty());
257}
258
Jonas Olsson6b1985d2018-07-05 09:59:48259TEST(ToString, SanityCheck) {
260 EXPECT_EQ(ToString(true), "true");
261 EXPECT_EQ(ToString(false), "false");
henrike@webrtc.orgf0488722014-05-13 18:00:26262
Jonas Olsson6b1985d2018-07-05 09:59:48263 const char* c = "message";
264 EXPECT_EQ(ToString(c), c);
265 EXPECT_EQ(ToString(std::string(c)), c);
Harald Alvestrandcf796a22024-10-01 11:00:40266 char nonconst_c[] = "message";
267 EXPECT_EQ(ToString(nonconst_c), c);
268 EXPECT_EQ(ToString(&nonconst_c[0]), c);
henrike@webrtc.orgf0488722014-05-13 18:00:26269
Jonas Olsson6b1985d2018-07-05 09:59:48270 EXPECT_EQ(ToString(short{-123}), "-123");
271 EXPECT_EQ(ToString((unsigned short)123), "123");
272 EXPECT_EQ(ToString(int{-123}), "-123");
273 EXPECT_EQ(ToString((unsigned int)123), "123");
274 EXPECT_EQ(ToString((long int)-123), "-123");
275 EXPECT_EQ(ToString((unsigned long int)123), "123");
276 EXPECT_EQ(ToString((long long int)-123), "-123");
277 EXPECT_EQ(ToString((unsigned long long int)123), "123");
Jonas Olsson6b1985d2018-07-05 09:59:48278 EXPECT_EQ(ToString(0.5), "0.5");
Tommi187a4362024-07-09 08:29:44279 int i = 10;
280 EXPECT_EQ(StringFormat("%p", &i), ToString(&i));
henrike@webrtc.orgf0488722014-05-13 18:00:26281}
282
Jonas Olsson6b1985d2018-07-05 09:59:48283template <typename T>
284void ParsesTo(std::string s, T t) {
285 T value;
286 EXPECT_TRUE(FromString(s, &value));
287 EXPECT_EQ(value, t);
henrike@webrtc.orgf0488722014-05-13 18:00:26288}
289
Jonas Olsson6b1985d2018-07-05 09:59:48290TEST(FromString, DecodeValid) {
291 ParsesTo("true", true);
292 ParsesTo("false", false);
293
294 ParsesTo("105", 105);
295 ParsesTo("0.25", 0.25);
296}
297
298template <typename T>
299void FailsToParse(std::string s) {
300 T value;
301 EXPECT_FALSE(FromString(s, &value)) << "[" << s << "]";
302}
303
304TEST(FromString, DecodeInvalid) {
305 FailsToParse<bool>("True");
306 FailsToParse<bool>("0");
307 FailsToParse<bool>("yes");
308
309 FailsToParse<int>("0.5");
310 FailsToParse<int>("XIV");
311 FailsToParse<double>("");
312 FailsToParse<double>(" ");
313 FailsToParse<int>("1 2");
314}
315
316template <typename T>
317void RoundTrip(T t) {
318 std::string s = ToString(t);
319 T value;
320 EXPECT_TRUE(FromString(s, &value));
321 EXPECT_EQ(value, t);
322}
323
324TEST(FromString, RoundTrip) {
325 RoundTrip<int>(123);
326 RoundTrip(false);
327 RoundTrip(true);
328 RoundTrip(0.5);
329 RoundTrip(-15l);
henrike@webrtc.orgf0488722014-05-13 18:00:26330}
deadbeef0a6c4ca2015-10-06 18:38:28331
henrike@webrtc.orgf0488722014-05-13 18:00:26332} // namespace rtc