rippled
StringUtilities_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/Slice.h>
21 #include <ripple/basics/StringUtilities.h>
22 #include <ripple/basics/ToString.h>
23 #include <ripple/beast/unit_test.h>
24 
25 namespace ripple {
26 
27 class StringUtilities_test : public beast::unit_test::suite
28 {
29 public:
30  void
31  testUnHexSuccess(std::string const& strIn, std::string const& strExpected)
32  {
33  auto rv = strUnHex(strIn);
34  BEAST_EXPECT(rv);
35  BEAST_EXPECT(makeSlice(*rv) == makeSlice(strExpected));
36  }
37 
38  void
40  {
41  auto rv = strUnHex(strIn);
42  BEAST_EXPECT(!rv);
43  }
44 
45  void
47  {
48  testcase("strUnHex");
49 
50  testUnHexSuccess("526970706c6544", "RippleD");
51  testUnHexSuccess("A", "\n");
52  testUnHexSuccess("0A", "\n");
53  testUnHexSuccess("D0A", "\r\n");
54  testUnHexSuccess("0D0A", "\r\n");
55  testUnHexSuccess("200D0A", " \r\n");
56  testUnHexSuccess("282A2B2C2D2E2F29", "(*+,-./)");
57 
58  // Check for things which contain some or only invalid characters
59  testUnHexFailure("123X");
60  testUnHexFailure("V");
61  testUnHexFailure("XRP");
62  }
63 
64  void
66  {
67  testcase("parseUrl");
68 
69  // Expected passes.
70  {
71  parsedURL pUrl;
72  BEAST_EXPECT(parseUrl(pUrl, "scheme://"));
73  BEAST_EXPECT(pUrl.scheme == "scheme");
74  BEAST_EXPECT(pUrl.username.empty());
75  BEAST_EXPECT(pUrl.password.empty());
76  BEAST_EXPECT(pUrl.domain.empty());
77  BEAST_EXPECT(!pUrl.port);
78  // RFC 3986:
79  // > In general, a URI that uses the generic syntax for authority
80  // with an empty path should be normalized to a path of "/".
81  // Do we want to normalize paths?
82  BEAST_EXPECT(pUrl.path.empty());
83  }
84 
85  {
86  parsedURL pUrl;
87  BEAST_EXPECT(parseUrl(pUrl, "scheme:///"));
88  BEAST_EXPECT(pUrl.scheme == "scheme");
89  BEAST_EXPECT(pUrl.username.empty());
90  BEAST_EXPECT(pUrl.password.empty());
91  BEAST_EXPECT(pUrl.domain.empty());
92  BEAST_EXPECT(!pUrl.port);
93  BEAST_EXPECT(pUrl.path == "/");
94  }
95 
96  {
97  parsedURL pUrl;
98  BEAST_EXPECT(parseUrl(pUrl, "lower://domain"));
99  BEAST_EXPECT(pUrl.scheme == "lower");
100  BEAST_EXPECT(pUrl.username.empty());
101  BEAST_EXPECT(pUrl.password.empty());
102  BEAST_EXPECT(pUrl.domain == "domain");
103  BEAST_EXPECT(!pUrl.port);
104  BEAST_EXPECT(pUrl.path.empty());
105  }
106 
107  {
108  parsedURL pUrl;
109  BEAST_EXPECT(parseUrl(pUrl, "UPPER://domain:234/"));
110  BEAST_EXPECT(pUrl.scheme == "upper");
111  BEAST_EXPECT(pUrl.username.empty());
112  BEAST_EXPECT(pUrl.password.empty());
113  BEAST_EXPECT(pUrl.domain == "domain");
114  BEAST_EXPECT(*pUrl.port == 234);
115  BEAST_EXPECT(pUrl.path == "/");
116  }
117 
118  {
119  parsedURL pUrl;
120  BEAST_EXPECT(parseUrl(pUrl, "Mixed://domain/path"));
121  BEAST_EXPECT(pUrl.scheme == "mixed");
122  BEAST_EXPECT(pUrl.username.empty());
123  BEAST_EXPECT(pUrl.password.empty());
124  BEAST_EXPECT(pUrl.domain == "domain");
125  BEAST_EXPECT(!pUrl.port);
126  BEAST_EXPECT(pUrl.path == "/path");
127  }
128 
129  {
130  parsedURL pUrl;
131  BEAST_EXPECT(parseUrl(pUrl, "scheme://[::1]:123/path"));
132  BEAST_EXPECT(pUrl.scheme == "scheme");
133  BEAST_EXPECT(pUrl.username.empty());
134  BEAST_EXPECT(pUrl.password.empty());
135  BEAST_EXPECT(pUrl.domain == "::1");
136  BEAST_EXPECT(*pUrl.port == 123);
137  BEAST_EXPECT(pUrl.path == "/path");
138  }
139 
140  {
141  parsedURL pUrl;
142  BEAST_EXPECT(
143  parseUrl(pUrl, "scheme://user:pass@domain:123/abc:321"));
144  BEAST_EXPECT(pUrl.scheme == "scheme");
145  BEAST_EXPECT(pUrl.username == "user");
146  BEAST_EXPECT(pUrl.password == "pass");
147  BEAST_EXPECT(pUrl.domain == "domain");
148  BEAST_EXPECT(*pUrl.port == 123);
149  BEAST_EXPECT(pUrl.path == "/abc:321");
150  }
151 
152  {
153  parsedURL pUrl;
154  BEAST_EXPECT(parseUrl(pUrl, "scheme://user@domain:123/abc:321"));
155  BEAST_EXPECT(pUrl.scheme == "scheme");
156  BEAST_EXPECT(pUrl.username == "user");
157  BEAST_EXPECT(pUrl.password.empty());
158  BEAST_EXPECT(pUrl.domain == "domain");
159  BEAST_EXPECT(*pUrl.port == 123);
160  BEAST_EXPECT(pUrl.path == "/abc:321");
161  }
162 
163  {
164  parsedURL pUrl;
165  BEAST_EXPECT(parseUrl(pUrl, "scheme://:pass@domain:123/abc:321"));
166  BEAST_EXPECT(pUrl.scheme == "scheme");
167  BEAST_EXPECT(pUrl.username.empty());
168  BEAST_EXPECT(pUrl.password == "pass");
169  BEAST_EXPECT(pUrl.domain == "domain");
170  BEAST_EXPECT(*pUrl.port == 123);
171  BEAST_EXPECT(pUrl.path == "/abc:321");
172  }
173 
174  {
175  parsedURL pUrl;
176  BEAST_EXPECT(parseUrl(pUrl, "scheme://domain:123/abc:321"));
177  BEAST_EXPECT(pUrl.scheme == "scheme");
178  BEAST_EXPECT(pUrl.username.empty());
179  BEAST_EXPECT(pUrl.password.empty());
180  BEAST_EXPECT(pUrl.domain == "domain");
181  BEAST_EXPECT(*pUrl.port == 123);
182  BEAST_EXPECT(pUrl.path == "/abc:321");
183  }
184 
185  {
186  parsedURL pUrl;
187  BEAST_EXPECT(parseUrl(pUrl, "scheme://user:pass@domain/abc:321"));
188  BEAST_EXPECT(pUrl.scheme == "scheme");
189  BEAST_EXPECT(pUrl.username == "user");
190  BEAST_EXPECT(pUrl.password == "pass");
191  BEAST_EXPECT(pUrl.domain == "domain");
192  BEAST_EXPECT(!pUrl.port);
193  BEAST_EXPECT(pUrl.path == "/abc:321");
194  }
195 
196  {
197  parsedURL pUrl;
198  BEAST_EXPECT(parseUrl(pUrl, "scheme://user@domain/abc:321"));
199  BEAST_EXPECT(pUrl.scheme == "scheme");
200  BEAST_EXPECT(pUrl.username == "user");
201  BEAST_EXPECT(pUrl.password.empty());
202  BEAST_EXPECT(pUrl.domain == "domain");
203  BEAST_EXPECT(!pUrl.port);
204  BEAST_EXPECT(pUrl.path == "/abc:321");
205  }
206 
207  {
208  parsedURL pUrl;
209  BEAST_EXPECT(parseUrl(pUrl, "scheme://:pass@domain/abc:321"));
210  BEAST_EXPECT(pUrl.scheme == "scheme");
211  BEAST_EXPECT(pUrl.username.empty());
212  BEAST_EXPECT(pUrl.password == "pass");
213  BEAST_EXPECT(pUrl.domain == "domain");
214  BEAST_EXPECT(!pUrl.port);
215  BEAST_EXPECT(pUrl.path == "/abc:321");
216  }
217 
218  {
219  parsedURL pUrl;
220  BEAST_EXPECT(parseUrl(pUrl, "scheme://domain/abc:321"));
221  BEAST_EXPECT(pUrl.scheme == "scheme");
222  BEAST_EXPECT(pUrl.username.empty());
223  BEAST_EXPECT(pUrl.password.empty());
224  BEAST_EXPECT(pUrl.domain == "domain");
225  BEAST_EXPECT(!pUrl.port);
226  BEAST_EXPECT(pUrl.path == "/abc:321");
227  }
228 
229  {
230  parsedURL pUrl;
231  BEAST_EXPECT(parseUrl(pUrl, "scheme:///path/to/file"));
232  BEAST_EXPECT(pUrl.scheme == "scheme");
233  BEAST_EXPECT(pUrl.username.empty());
234  BEAST_EXPECT(pUrl.password.empty());
235  BEAST_EXPECT(pUrl.domain.empty());
236  BEAST_EXPECT(!pUrl.port);
237  BEAST_EXPECT(pUrl.path == "/path/to/file");
238  }
239 
240  {
241  parsedURL pUrl;
242  BEAST_EXPECT(
243  parseUrl(pUrl, "scheme://user:pass@domain/path/with/an@sign"));
244  BEAST_EXPECT(pUrl.scheme == "scheme");
245  BEAST_EXPECT(pUrl.username == "user");
246  BEAST_EXPECT(pUrl.password == "pass");
247  BEAST_EXPECT(pUrl.domain == "domain");
248  BEAST_EXPECT(!pUrl.port);
249  BEAST_EXPECT(pUrl.path == "/path/with/an@sign");
250  }
251 
252  {
253  parsedURL pUrl;
254  BEAST_EXPECT(parseUrl(pUrl, "scheme://domain/path/with/an@sign"));
255  BEAST_EXPECT(pUrl.scheme == "scheme");
256  BEAST_EXPECT(pUrl.username.empty());
257  BEAST_EXPECT(pUrl.password.empty());
258  BEAST_EXPECT(pUrl.domain == "domain");
259  BEAST_EXPECT(!pUrl.port);
260  BEAST_EXPECT(pUrl.path == "/path/with/an@sign");
261  }
262 
263  {
264  parsedURL pUrl;
265  BEAST_EXPECT(parseUrl(pUrl, "scheme://:999/"));
266  BEAST_EXPECT(pUrl.scheme == "scheme");
267  BEAST_EXPECT(pUrl.username.empty());
268  BEAST_EXPECT(pUrl.password.empty());
269  BEAST_EXPECT(pUrl.domain == ":999");
270  BEAST_EXPECT(!pUrl.port);
271  BEAST_EXPECT(pUrl.path == "/");
272  }
273 
274  {
275  parsedURL pUrl;
276  BEAST_EXPECT(parseUrl(pUrl, "http://::1:1234/validators"));
277  BEAST_EXPECT(pUrl.scheme == "http");
278  BEAST_EXPECT(pUrl.username.empty());
279  BEAST_EXPECT(pUrl.password.empty());
280  BEAST_EXPECT(pUrl.domain == "::0.1.18.52");
281  BEAST_EXPECT(!pUrl.port);
282  BEAST_EXPECT(pUrl.path == "/validators");
283  }
284 
285  // Expected fails.
286  {
287  parsedURL pUrl;
288  BEAST_EXPECT(!parseUrl(pUrl, ""));
289  BEAST_EXPECT(!parseUrl(pUrl, "nonsense"));
290  BEAST_EXPECT(!parseUrl(pUrl, "://"));
291  BEAST_EXPECT(!parseUrl(pUrl, ":///"));
292  BEAST_EXPECT(
293  !parseUrl(pUrl, "scheme://user:pass@domain:65536/abc:321"));
294  BEAST_EXPECT(!parseUrl(pUrl, "UPPER://domain:23498765/"));
295  BEAST_EXPECT(!parseUrl(pUrl, "UPPER://domain:0/"));
296  BEAST_EXPECT(!parseUrl(pUrl, "UPPER://domain:+7/"));
297  BEAST_EXPECT(!parseUrl(pUrl, "UPPER://domain:-7234/"));
298  BEAST_EXPECT(!parseUrl(pUrl, "UPPER://domain:@#$56!/"));
299  }
300 
301  {
302  std::string strUrl("s://" + std::string(8192, ':'));
303  parsedURL pUrl;
304  BEAST_EXPECT(!parseUrl(pUrl, strUrl));
305  }
306  }
307 
308  void
310  {
311  testcase("toString");
312  auto result = to_string("hello");
313  BEAST_EXPECT(result == "hello");
314  }
315 
316  void
317  run() override
318  {
319  testParseUrl();
320  testUnHex();
321  testToString();
322  }
323 };
324 
325 BEAST_DEFINE_TESTSUITE(StringUtilities, ripple_basics, ripple);
326 
327 } // namespace ripple
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:241
ripple::StringUtilities_test::run
void run() override
Definition: StringUtilities_test.cpp:317
std::string
STL class.
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::parsedURL
Definition: StringUtilities.h:116
ripple::parsedURL::password
std::string password
Definition: StringUtilities.h:122
ripple::parsedURL::username
std::string username
Definition: StringUtilities.h:121
ripple::parsedURL::path
std::string path
Definition: StringUtilities.h:125
ripple::StringUtilities_test
Definition: StringUtilities_test.cpp:27
ripple::StringUtilities_test::testUnHexSuccess
void testUnHexSuccess(std::string const &strIn, std::string const &strExpected)
Definition: StringUtilities_test.cpp:31
ripple::StringUtilities_test::testParseUrl
void testParseUrl()
Definition: StringUtilities_test.cpp:65
ripple::parsedURL::port
std::optional< std::uint16_t > port
Definition: StringUtilities.h:124
ripple::parseUrl
bool parseUrl(parsedURL &pUrl, std::string const &strUrl)
Definition: StringUtilities.cpp:47
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::string::empty
T empty(T... args)
ripple::parsedURL::scheme
std::string scheme
Definition: StringUtilities.h:120
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::StringUtilities_test::testUnHex
void testUnHex()
Definition: StringUtilities_test.cpp:46
ripple::parsedURL::domain
std::string domain
Definition: StringUtilities.h:123
ripple::StringUtilities_test::testToString
void testToString()
Definition: StringUtilities_test.cpp:309
ripple::StringUtilities_test::testUnHexFailure
void testUnHexFailure(std::string const &strIn)
Definition: StringUtilities_test.cpp:39
ripple::strUnHex
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Definition: StringUtilities.h:50