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 testUnHexSuccess (std::string const& strIn, std::string const& strExpected)
31  {
32  auto rv = strUnHex (strIn);
33  BEAST_EXPECT(rv);
34  BEAST_EXPECT(makeSlice(*rv) == makeSlice(strExpected));
35  }
36 
37  void testUnHexFailure (std::string const& strIn)
38  {
39  auto rv = strUnHex (strIn);
40  BEAST_EXPECT(! rv);
41  }
42 
43  void testUnHex ()
44  {
45  testcase ("strUnHex");
46 
47  testUnHexSuccess ("526970706c6544", "RippleD");
48  testUnHexSuccess ("A", "\n");
49  testUnHexSuccess ("0A", "\n");
50  testUnHexSuccess ("D0A", "\r\n");
51  testUnHexSuccess ("0D0A", "\r\n");
52  testUnHexSuccess ("200D0A", " \r\n");
53  testUnHexSuccess ("282A2B2C2D2E2F29", "(*+,-./)");
54 
55  // Check for things which contain some or only invalid characters
56  testUnHexFailure ("123X");
57  testUnHexFailure ("V");
58  testUnHexFailure ("XRP");
59  }
60 
61  void testParseUrl ()
62  {
63  testcase ("parseUrl");
64 
65  // Expected passes.
66  {
67  parsedURL pUrl;
68  BEAST_EXPECT(parseUrl (pUrl, "scheme://"));
69  BEAST_EXPECT(pUrl.scheme == "scheme");
70  BEAST_EXPECT(pUrl.username.empty());
71  BEAST_EXPECT(pUrl.password.empty());
72  BEAST_EXPECT(pUrl.domain.empty());
73  BEAST_EXPECT(! pUrl.port);
74  // RFC 3986:
75  // > In general, a URI that uses the generic syntax for authority
76  // with an empty path should be normalized to a path of "/".
77  // Do we want to normalize paths?
78  BEAST_EXPECT(pUrl.path.empty());
79  }
80 
81  {
82  parsedURL pUrl;
83  BEAST_EXPECT(parseUrl (pUrl, "scheme:///"));
84  BEAST_EXPECT(pUrl.scheme == "scheme");
85  BEAST_EXPECT(pUrl.username.empty());
86  BEAST_EXPECT(pUrl.password.empty());
87  BEAST_EXPECT(pUrl.domain.empty());
88  BEAST_EXPECT(! pUrl.port);
89  BEAST_EXPECT(pUrl.path == "/");
90  }
91 
92  {
93  parsedURL pUrl;
94  BEAST_EXPECT(parseUrl (pUrl, "lower://domain"));
95  BEAST_EXPECT(pUrl.scheme == "lower");
96  BEAST_EXPECT(pUrl.username.empty());
97  BEAST_EXPECT(pUrl.password.empty());
98  BEAST_EXPECT(pUrl.domain == "domain");
99  BEAST_EXPECT(! pUrl.port);
100  BEAST_EXPECT(pUrl.path.empty());
101  }
102 
103  {
104  parsedURL pUrl;
105  BEAST_EXPECT(parseUrl (pUrl, "UPPER://domain:234/"));
106  BEAST_EXPECT(pUrl.scheme == "upper");
107  BEAST_EXPECT(pUrl.username.empty());
108  BEAST_EXPECT(pUrl.password.empty());
109  BEAST_EXPECT(pUrl.domain == "domain");
110  BEAST_EXPECT(*pUrl.port == 234);
111  BEAST_EXPECT(pUrl.path == "/");
112  }
113 
114  {
115  parsedURL pUrl;
116  BEAST_EXPECT(parseUrl (pUrl, "Mixed://domain/path"));
117  BEAST_EXPECT(pUrl.scheme == "mixed");
118  BEAST_EXPECT(pUrl.username.empty());
119  BEAST_EXPECT(pUrl.password.empty());
120  BEAST_EXPECT(pUrl.domain == "domain");
121  BEAST_EXPECT(! pUrl.port);
122  BEAST_EXPECT(pUrl.path == "/path");
123  }
124 
125  {
126  parsedURL pUrl;
127  BEAST_EXPECT(parseUrl (pUrl, "scheme://[::1]:123/path"));
128  BEAST_EXPECT(pUrl.scheme == "scheme");
129  BEAST_EXPECT(pUrl.username.empty());
130  BEAST_EXPECT(pUrl.password.empty());
131  BEAST_EXPECT(pUrl.domain == "::1");
132  BEAST_EXPECT(*pUrl.port == 123);
133  BEAST_EXPECT(pUrl.path == "/path");
134  }
135 
136  {
137  parsedURL pUrl;
138  BEAST_EXPECT(parseUrl (pUrl, "scheme://user:pass@domain:123/abc:321"));
139  BEAST_EXPECT(pUrl.scheme == "scheme");
140  BEAST_EXPECT(pUrl.username == "user");
141  BEAST_EXPECT(pUrl.password == "pass");
142  BEAST_EXPECT(pUrl.domain == "domain");
143  BEAST_EXPECT(*pUrl.port == 123);
144  BEAST_EXPECT(pUrl.path == "/abc:321");
145  }
146 
147  {
148  parsedURL pUrl;
149  BEAST_EXPECT(parseUrl (pUrl, "scheme://user@domain:123/abc:321"));
150  BEAST_EXPECT(pUrl.scheme == "scheme");
151  BEAST_EXPECT(pUrl.username == "user");
152  BEAST_EXPECT(pUrl.password.empty());
153  BEAST_EXPECT(pUrl.domain == "domain");
154  BEAST_EXPECT(*pUrl.port == 123);
155  BEAST_EXPECT(pUrl.path == "/abc:321");
156  }
157 
158  {
159  parsedURL pUrl;
160  BEAST_EXPECT(parseUrl (pUrl, "scheme://:pass@domain:123/abc:321"));
161  BEAST_EXPECT(pUrl.scheme == "scheme");
162  BEAST_EXPECT(pUrl.username.empty());
163  BEAST_EXPECT(pUrl.password == "pass");
164  BEAST_EXPECT(pUrl.domain == "domain");
165  BEAST_EXPECT(*pUrl.port == 123);
166  BEAST_EXPECT(pUrl.path == "/abc:321");
167  }
168 
169  {
170  parsedURL pUrl;
171  BEAST_EXPECT(parseUrl (pUrl, "scheme://domain:123/abc:321"));
172  BEAST_EXPECT(pUrl.scheme == "scheme");
173  BEAST_EXPECT(pUrl.username.empty());
174  BEAST_EXPECT(pUrl.password.empty());
175  BEAST_EXPECT(pUrl.domain == "domain");
176  BEAST_EXPECT(*pUrl.port == 123);
177  BEAST_EXPECT(pUrl.path == "/abc:321");
178  }
179 
180  {
181  parsedURL pUrl;
182  BEAST_EXPECT(parseUrl (pUrl, "scheme://user:pass@domain/abc:321"));
183  BEAST_EXPECT(pUrl.scheme == "scheme");
184  BEAST_EXPECT(pUrl.username == "user");
185  BEAST_EXPECT(pUrl.password == "pass");
186  BEAST_EXPECT(pUrl.domain == "domain");
187  BEAST_EXPECT(! pUrl.port);
188  BEAST_EXPECT(pUrl.path == "/abc:321");
189  }
190 
191  {
192  parsedURL pUrl;
193  BEAST_EXPECT(parseUrl (pUrl, "scheme://user@domain/abc:321"));
194  BEAST_EXPECT(pUrl.scheme == "scheme");
195  BEAST_EXPECT(pUrl.username == "user");
196  BEAST_EXPECT(pUrl.password.empty());
197  BEAST_EXPECT(pUrl.domain == "domain");
198  BEAST_EXPECT(! pUrl.port);
199  BEAST_EXPECT(pUrl.path == "/abc:321");
200  }
201 
202  {
203  parsedURL pUrl;
204  BEAST_EXPECT(parseUrl (pUrl, "scheme://:pass@domain/abc:321"));
205  BEAST_EXPECT(pUrl.scheme == "scheme");
206  BEAST_EXPECT(pUrl.username.empty());
207  BEAST_EXPECT(pUrl.password == "pass");
208  BEAST_EXPECT(pUrl.domain == "domain");
209  BEAST_EXPECT(! pUrl.port);
210  BEAST_EXPECT(pUrl.path == "/abc:321");
211  }
212 
213  {
214  parsedURL pUrl;
215  BEAST_EXPECT(parseUrl (pUrl, "scheme://domain/abc:321"));
216  BEAST_EXPECT(pUrl.scheme == "scheme");
217  BEAST_EXPECT(pUrl.username.empty());
218  BEAST_EXPECT(pUrl.password.empty());
219  BEAST_EXPECT(pUrl.domain == "domain");
220  BEAST_EXPECT(! pUrl.port);
221  BEAST_EXPECT(pUrl.path == "/abc:321");
222  }
223 
224  {
225  parsedURL pUrl;
226  BEAST_EXPECT(parseUrl (pUrl, "scheme:///path/to/file"));
227  BEAST_EXPECT(pUrl.scheme == "scheme");
228  BEAST_EXPECT(pUrl.username.empty());
229  BEAST_EXPECT(pUrl.password.empty());
230  BEAST_EXPECT(pUrl.domain.empty());
231  BEAST_EXPECT(! pUrl.port);
232  BEAST_EXPECT(pUrl.path == "/path/to/file");
233  }
234 
235  {
236  parsedURL pUrl;
237  BEAST_EXPECT(parseUrl (
238  pUrl, "scheme://user:pass@domain/path/with/an@sign"));
239  BEAST_EXPECT(pUrl.scheme == "scheme");
240  BEAST_EXPECT(pUrl.username == "user");
241  BEAST_EXPECT(pUrl.password == "pass");
242  BEAST_EXPECT(pUrl.domain == "domain");
243  BEAST_EXPECT(! pUrl.port);
244  BEAST_EXPECT(pUrl.path == "/path/with/an@sign");
245  }
246 
247  {
248  parsedURL pUrl;
249  BEAST_EXPECT(parseUrl (
250  pUrl, "scheme://domain/path/with/an@sign"));
251  BEAST_EXPECT(pUrl.scheme == "scheme");
252  BEAST_EXPECT(pUrl.username.empty());
253  BEAST_EXPECT(pUrl.password.empty());
254  BEAST_EXPECT(pUrl.domain == "domain");
255  BEAST_EXPECT(! pUrl.port);
256  BEAST_EXPECT(pUrl.path == "/path/with/an@sign");
257  }
258 
259  {
260  parsedURL pUrl;
261  BEAST_EXPECT(parseUrl (pUrl, "scheme://:999/"));
262  BEAST_EXPECT(pUrl.scheme == "scheme");
263  BEAST_EXPECT(pUrl.username.empty());
264  BEAST_EXPECT(pUrl.password.empty());
265  BEAST_EXPECT(pUrl.domain == ":999");
266  BEAST_EXPECT(! pUrl.port);
267  BEAST_EXPECT(pUrl.path == "/");
268  }
269 
270  {
271  parsedURL pUrl;
272  BEAST_EXPECT(parseUrl (pUrl, "http://::1:1234/validators"));
273  BEAST_EXPECT(pUrl.scheme == "http");
274  BEAST_EXPECT(pUrl.username.empty());
275  BEAST_EXPECT(pUrl.password.empty());
276  BEAST_EXPECT(pUrl.domain == "::0.1.18.52");
277  BEAST_EXPECT(! pUrl.port);
278  BEAST_EXPECT(pUrl.path == "/validators");
279  }
280 
281  // Expected fails.
282  {
283  parsedURL pUrl;
284  BEAST_EXPECT(! parseUrl (pUrl, ""));
285  BEAST_EXPECT(! parseUrl (pUrl, "nonsense"));
286  BEAST_EXPECT(! parseUrl (pUrl, "://"));
287  BEAST_EXPECT(! parseUrl (pUrl, ":///"));
288  }
289 
290  {
291  std::string strUrl("s://" + std::string(8192, ':'));
292  parsedURL pUrl;
293  BEAST_EXPECT(! parseUrl (pUrl, strUrl));
294  }
295  }
296 
297  void testToString ()
298  {
299  testcase ("toString");
300  auto result = to_string("hello");
301  BEAST_EXPECT(result == "hello");
302  }
303 
304  void run () override
305  {
306  testParseUrl ();
307  testUnHex ();
308  testToString ();
309  }
310 };
311 
312 BEAST_DEFINE_TESTSUITE(StringUtilities, ripple_basics, ripple);
313 
314 } // 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:199
ripple::StringUtilities_test::run
void run() override
Definition: StringUtilities_test.cpp:304
std::string
STL class.
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::parsedURL
Definition: StringUtilities.h:122
ripple::parsedURL::password
std::string password
Definition: StringUtilities.h:128
ripple::strUnHex
boost::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Definition: StringUtilities.h:69
ripple::parsedURL::username
std::string username
Definition: StringUtilities.h:127
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::parsedURL::path
std::string path
Definition: StringUtilities.h:131
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:30
ripple::StringUtilities_test::testParseUrl
void testParseUrl()
Definition: StringUtilities_test.cpp:61
ripple::parseUrl
bool parseUrl(parsedURL &pUrl, std::string const &strUrl)
Definition: StringUtilities.cpp:53
ripple::parsedURL::port
boost::optional< std::uint16_t > port
Definition: StringUtilities.h:130
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:126
ripple::StringUtilities_test::testUnHex
void testUnHex()
Definition: StringUtilities_test.cpp:43
ripple::parsedURL::domain
std::string domain
Definition: StringUtilities.h:129
ripple::StringUtilities_test::testToString
void testToString()
Definition: StringUtilities_test.cpp:297
ripple::StringUtilities_test::testUnHexFailure
void testUnHexFailure(std::string const &strIn)
Definition: StringUtilities_test.cpp:37