Electroneum
Loading...
Searching...
No Matches
epee_utils.cpp
Go to the documentation of this file.
1// Copyrights(c) 2017-2021, The Electroneum Project
2// Copyrights(c) 2014-2019, The Monero Project
3//
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without modification, are
7// permitted provided that the following conditions are met:
8//
9// 1. Redistributions of source code must retain the above copyright notice, this list of
10// conditions and the following disclaimer.
11//
12// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13// of conditions and the following disclaimer in the documentation and/or other
14// materials provided with the distribution.
15//
16// 3. Neither the name of the copyright holder nor the names of its contributors may be
17// used to endorse or promote products derived from this software without specific
18// prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30#include <array>
31#include <boost/endian/conversion.hpp>
32#include <boost/range/algorithm/equal.hpp>
33#include <boost/range/algorithm_ext/iota.hpp>
34#include <cstdint>
35#include <gtest/gtest.h>
36#include <iterator>
37#include <string>
38#include <sstream>
39#include <vector>
40
41#ifndef _WIN32
42# include <arpa/inet.h>
43#endif
44
47#include "hex.h"
48#include "net/net_utils_base.h"
49#include "net/local_ip.h"
50#include "net/buffer.h"
52#include "span.h"
53#include "string_tools.h"
55
56namespace
57{
58 template<typename Destination, typename Source>
59 bool can_construct()
60 {
61 const unsigned count =
62 unsigned(std::is_constructible<Destination, Source>()) +
63 unsigned(std::is_constructible<Destination, Source&>()) +
64 unsigned(std::is_convertible<Source, Destination>()) +
65 unsigned(std::is_convertible<Source&, Destination>()) +
66 unsigned(std::is_assignable<Destination, Source>()) +
67 unsigned(std::is_assignable<Destination, Source&>());
68 EXPECT_TRUE(count == 6 || count == 0) <<
69 "Mismatch on construction results - " << count << " were true";
70 return count == 6;
71 }
72
73 // This is probably stressing the compiler more than the implementation ...
74 constexpr const epee::span<const char> test_string("a string");
75 static_assert(!test_string.empty(), "test failure");
76 static_assert(test_string.size() == 9, "test failure");
77 static_assert(test_string.size_bytes() == 9, "test_failure");
78 static_assert(test_string.begin() == test_string.cbegin(), "test failure");
79 static_assert(test_string.end() == test_string.cend(), "test failure");
80 static_assert(test_string.cend() - test_string.cbegin() == 9, "test failure");
81 static_assert(*test_string.cbegin() == 'a', "test failure");
82 static_assert(*(test_string.cend() - 2) == 'g', "test failure");
83 static_assert(
84 epee::span<const char>(test_string).cbegin() + 3 == test_string.cbegin() + 3,
85 "test failure"
86 );
87
88 static_assert(epee::span<char>().empty(), "test failure");
89 static_assert(epee::span<char>(nullptr).empty(), "test failure");
90 static_assert(epee::span<const char>("foo", 2).size() == 2, "test failure");
91
92 std::string std_to_hex(const std::vector<unsigned char>& source)
93 {
94 std::stringstream out;
95 out << std::hex;
96 for (const unsigned char byte : source)
97 {
98 out << std::setw(2) << std::setfill('0') << int(byte);
99 }
100 return out.str();
101 }
102
103 std::vector<unsigned char> get_all_bytes()
104 {
105 std::vector<unsigned char> out;
106 out.resize(256);
107 boost::range::iota(out, 0);
108 return out;
109 }
110
111 #define CHECK_EQUAL(lhs, rhs) \
112 EXPECT_TRUE( lhs == rhs ); \
113 EXPECT_TRUE( rhs == lhs ); \
114 EXPECT_FALSE( lhs != rhs ); \
115 EXPECT_FALSE( rhs != lhs ); \
116 EXPECT_FALSE( lhs < rhs ); \
117 EXPECT_FALSE( rhs < lhs ); \
118 EXPECT_TRUE( lhs <= rhs ); \
119 EXPECT_TRUE( rhs <= lhs ); \
120 EXPECT_FALSE( lhs > rhs ); \
121 EXPECT_FALSE( rhs > lhs ); \
122 EXPECT_TRUE( lhs >= rhs ); \
123 EXPECT_TRUE( rhs >= lhs )
124
125 #define CHECK_LESS(lhs, rhs) \
126 EXPECT_FALSE( lhs == rhs ); \
127 EXPECT_FALSE( rhs == lhs ); \
128 EXPECT_TRUE( lhs != rhs ); \
129 EXPECT_TRUE( rhs != lhs ); \
130 EXPECT_TRUE( lhs < rhs ); \
131 EXPECT_FALSE( rhs < lhs ); \
132 EXPECT_TRUE( lhs <= rhs ); \
133 EXPECT_FALSE( rhs <= lhs ); \
134 EXPECT_FALSE( lhs > rhs ); \
135 EXPECT_TRUE( rhs > lhs ); \
136 EXPECT_FALSE( lhs >= rhs ); \
137 EXPECT_TRUE( rhs >= lhs )
138
139 #ifdef BOOST_LITTLE_ENDIAN
140 #define CHECK_LESS_ENDIAN(lhs, rhs) CHECK_LESS( rhs , lhs )
141 #else
142 #define CHECK_LESS_ENDIAN(lhs, rhs) CHECK_LESS( lhs , rhs )
143 #endif
144}
145
147{
148 EXPECT_TRUE((std::is_same<std::size_t, typename epee::span<char>::size_type>()));
149 EXPECT_TRUE((std::is_same<std::ptrdiff_t, typename epee::span<char>::difference_type>()));
150 EXPECT_TRUE((std::is_same<char, typename epee::span<char>::value_type>()));
151 EXPECT_TRUE((std::is_same<char*, typename epee::span<char>::pointer>()));
152 EXPECT_TRUE((std::is_same<const char*, typename epee::span<char>::const_pointer>()));
153 EXPECT_TRUE((std::is_same<char*, typename epee::span<char>::iterator>()));
154 EXPECT_TRUE((std::is_same<const char*, typename epee::span<char>::const_iterator>()));
155 EXPECT_TRUE((std::is_same<char&, typename epee::span<char>::reference>()));
156 EXPECT_TRUE((std::is_same<const char&, typename epee::span<char>::const_reference>()));
157
158 EXPECT_TRUE((std::is_same<std::size_t, typename epee::span<const char>::size_type>()));
159 EXPECT_TRUE((std::is_same<std::ptrdiff_t, typename epee::span<const char>::difference_type>()));
160 EXPECT_TRUE((std::is_same<const char, typename epee::span<const char>::value_type>()));
161 EXPECT_TRUE((std::is_same<const char*, typename epee::span<const char>::pointer>()));
162 EXPECT_TRUE((std::is_same<const char*, typename epee::span<const char>::const_pointer>()));
163 EXPECT_TRUE((std::is_same<const char*, typename epee::span<const char>::iterator>()));
164 EXPECT_TRUE((std::is_same<const char*, typename epee::span<const char>::const_iterator>()));
165 EXPECT_TRUE((std::is_same<const char&, typename epee::span<const char>::reference>()));
166 EXPECT_TRUE((std::is_same<const char&, typename epee::span<const char>::const_reference>()));
167}
168
169TEST(Span, MutableConstruction)
170{
171 struct no_conversion{};
172 struct inherited : no_conversion {};
173
174 EXPECT_TRUE(std::is_constructible<epee::span<char>>());
175 EXPECT_TRUE((std::is_constructible<epee::span<char>, char*, std::size_t>()));
176 EXPECT_FALSE((std::is_constructible<epee::span<char>, const char*, std::size_t>()));
177 EXPECT_FALSE((std::is_constructible<epee::span<char>, unsigned char*, std::size_t>()));
178
179 EXPECT_TRUE(std::is_constructible<epee::span<no_conversion>>());
180 EXPECT_TRUE((std::is_constructible<epee::span<no_conversion>, no_conversion*, std::size_t>()));
181 EXPECT_FALSE((std::is_constructible<epee::span<no_conversion>, inherited*, std::size_t>()));
182
183 EXPECT_TRUE((can_construct<epee::span<char>, std::nullptr_t>()));
184 EXPECT_TRUE((can_construct<epee::span<char>, char(&)[1]>()));
185
186 EXPECT_FALSE((can_construct<epee::span<char>, std::vector<char>>()));
187 EXPECT_FALSE((can_construct<epee::span<char>, std::array<char, 1>>()));
188
189 EXPECT_FALSE((can_construct<epee::span<char>, std::wstring>()));
190 EXPECT_FALSE((can_construct<epee::span<char>, const std::vector<char>>()));
191 EXPECT_FALSE((can_construct<epee::span<char>, std::vector<unsigned char>>()));
192 EXPECT_FALSE((can_construct<epee::span<char>, const std::array<char, 1>>()));
193 EXPECT_FALSE((can_construct<epee::span<char>, std::array<unsigned char, 1>>()));
194 EXPECT_FALSE((can_construct<epee::span<char>, const char[1]>()));
195 EXPECT_FALSE((can_construct<epee::span<char>, unsigned char[1]>()));
198 EXPECT_FALSE((can_construct<epee::span<char>, no_conversion>()));
199}
200
201TEST(Span, ImmutableConstruction)
202{
203 struct no_conversion{};
204 struct inherited : no_conversion {};
205
206 EXPECT_TRUE(std::is_constructible<epee::span<const char>>());
207 EXPECT_TRUE((std::is_constructible<epee::span<const char>, char*, std::size_t>()));
208 EXPECT_TRUE((std::is_constructible<epee::span<const char>, const char*, std::size_t>()));
209 EXPECT_FALSE((std::is_constructible<epee::span<const char>, unsigned char*, std::size_t>()));
210
211 EXPECT_TRUE(std::is_constructible<epee::span<const no_conversion>>());
212 EXPECT_TRUE((std::is_constructible<epee::span<const no_conversion>, const no_conversion*, std::size_t>()));
213 EXPECT_TRUE((std::is_constructible<epee::span<const no_conversion>, no_conversion*, std::size_t>()));
214 EXPECT_FALSE((std::is_constructible<epee::span<const no_conversion>, const inherited*, std::size_t>()));
215 EXPECT_FALSE((std::is_constructible<epee::span<const no_conversion>, inherited*, std::size_t>()));
216
217 EXPECT_FALSE((can_construct<epee::span<const char>, std::string>()));
218 EXPECT_FALSE((can_construct<epee::span<const char>, std::vector<char>>()));
219 EXPECT_FALSE((can_construct<epee::span<const char>, const std::vector<char>>()));
220 EXPECT_FALSE((can_construct<epee::span<const char>, std::array<char, 1>>()));
221 EXPECT_FALSE((can_construct<epee::span<const char>, const std::array<char, 1>>()));
222
223 EXPECT_TRUE((can_construct<epee::span<const char>, std::nullptr_t>()));
224 EXPECT_TRUE((can_construct<epee::span<const char>, char[1]>()));
225 EXPECT_TRUE((can_construct<epee::span<const char>, const char[1]>()));
227
228 EXPECT_FALSE((can_construct<epee::span<const char>, std::wstring>()));
229 EXPECT_FALSE((can_construct<epee::span<const char>, std::vector<unsigned char>>()));
230 EXPECT_FALSE((can_construct<epee::span<const char>, std::array<unsigned char, 1>>()));
231 EXPECT_FALSE((can_construct<epee::span<const char>, unsigned char[1]>()));
233 EXPECT_FALSE((can_construct<epee::span<const char>, no_conversion>()));
234}
235
236TEST(Span, NoExcept)
237{
238 EXPECT_TRUE(std::is_nothrow_default_constructible<epee::span<char>>());
239 EXPECT_TRUE(std::is_nothrow_move_constructible<epee::span<char>>());
240 EXPECT_TRUE(std::is_nothrow_copy_constructible<epee::span<char>>());
241 EXPECT_TRUE(std::is_move_assignable<epee::span<char>>());
242 EXPECT_TRUE(std::is_copy_assignable<epee::span<char>>());
243
244 char data[10];
245 epee::span<char> lvalue(data);
246 const epee::span<char> clvalue(data);
247 EXPECT_TRUE(noexcept(epee::span<char>()));
248 EXPECT_TRUE(noexcept(epee::span<char>(nullptr)));
249 EXPECT_TRUE(noexcept(epee::span<char>(data)));
250 EXPECT_TRUE(noexcept(epee::span<char>(lvalue)));
251 EXPECT_TRUE(noexcept(epee::span<char>(clvalue)));
252
253 // conversion from mutable to immutable not yet implemented
254 // EXPECT_TRUE(noexcept(epee::span<const char>(lvalue)));
255 // EXPECT_TRUE(noexcept(epee::span<const char>(clvalue)));
256
258 EXPECT_TRUE(noexcept(lvalue = lvalue));
259 EXPECT_TRUE(noexcept(lvalue = clvalue));
260 EXPECT_TRUE(noexcept(lvalue = epee::span<char>(lvalue)));
261}
262
263TEST(Span, Nullptr)
264{
265 const auto check_empty = [](epee::span<const char> data)
266 {
267 EXPECT_TRUE(data.empty());
268 EXPECT_EQ(data.cbegin(), data.begin());
269 EXPECT_EQ(data.cend(), data.end());
270 EXPECT_EQ(data.cend(), data.cbegin());
271 EXPECT_EQ(0, data.size());
272 EXPECT_EQ(0, data.size_bytes());
273 };
274 check_empty({});
275 check_empty(nullptr);
276}
277
278TEST(Span, Writing)
279{
280 const int expected[] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
281 std::vector<int> source;
282
283 epee::span<int> span;
284 EXPECT_TRUE(span.empty());
285 EXPECT_EQ(0, span.size());
286 EXPECT_EQ(0, span.size_bytes());
287
288 source.resize(15);
289 span = {source.data(), source.size()};
290 EXPECT_FALSE(span.empty());
291 EXPECT_EQ(15, span.size());
292 EXPECT_EQ(15 * 4, span.size_bytes());
293
294 boost::range::iota(span, -5);
295 EXPECT_EQ(span.begin(), span.cbegin());
296 EXPECT_EQ(span.end(), span.cend());
297 EXPECT_TRUE(boost::range::equal(expected, source));
298 EXPECT_TRUE(boost::range::equal(expected, span));
299}
300
301TEST(Span, RemovePrefix)
302{
303 const std::array<unsigned, 4> expected{0, 1, 2, 3};
304 auto span = epee::to_span(expected);
305
306 EXPECT_EQ(expected.begin(), span.begin());
307 EXPECT_EQ(expected.end(), span.end());
308
309 EXPECT_EQ(2u, span.remove_prefix(2));
310 EXPECT_EQ(expected.begin() + 2, span.begin());
311 EXPECT_EQ(expected.end(), span.end());
312
313 EXPECT_EQ(2u, span.remove_prefix(3));
314 EXPECT_EQ(span.begin(), span.end());
315 EXPECT_EQ(expected.end(), span.begin());
316
317 EXPECT_EQ(0u, span.remove_prefix(100));
318}
319
320TEST(Span, ToByteSpan)
321{
322 const char expected[] = {56, 44, 11, 5};
324 boost::range::equal(
325 std::array<std::uint8_t, 4>{{56, 44, 11, 5}},
327 )
328 );
330 boost::range::equal(
331 std::array<char, 4>{{56, 44, 11, 5}},
333 )
334 );
335}
336
337TEST(Span, AsByteSpan)
338{
339 struct some_pod { char value[4]; };
340 const some_pod immutable {{ 5, 10, 12, 127 }};
342 boost::range::equal(
343 std::array<unsigned char, 4>{{5, 10, 12, 127}},
344 epee::as_byte_span(immutable)
345 )
346 );
348 boost::range::equal(
349 std::array<std::uint8_t, 3>{{'a', 'y', 0x00}}, epee::as_byte_span("ay")
350 )
351 );
352}
353
354TEST(Span, AsMutByteSpan)
355{
356 struct some_pod { char value[4]; };
357 some_pod actual {};
358
359 auto span = epee::as_mut_byte_span(actual);
360 boost::range::iota(span, 1);
362 boost::range::equal(
363 std::array<unsigned char, 4>{{1, 2, 3, 4}}, actual.value
364 )
365 );
366}
367
368TEST(Span, ToMutSpan)
369{
370 std::vector<unsigned> mut;
371 mut.resize(4);
372
373 auto span = epee::to_mut_span(mut);
374 boost::range::iota(span, 1);
375 EXPECT_EQ((std::vector<unsigned>{1, 2, 3, 4}), mut);
376}
377
378TEST(ToHex, String)
379{
380 EXPECT_TRUE(epee::to_hex::string(nullptr).empty());
381 EXPECT_EQ(
382 std::string{"ffab0100"},
384 );
385
386 const std::vector<unsigned char> all_bytes = get_all_bytes();
387 EXPECT_EQ(
388 std_to_hex(all_bytes), epee::to_hex::string(epee::to_span(all_bytes))
389 );
390
391}
392
393TEST(FromHex, String)
394{
395 // the source data to encode and decode
396 std::vector<uint8_t> source{{ 0x00, 0xFF, 0x0F, 0xF0 }};
397
398 // encode and decode the data
399 auto hex = epee::to_hex::string({ source.data(), source.size() });
400 auto decoded = epee::from_hex::vector(hex);
401
402 // encoded should be twice the size and should decode to the exact same data
403 EXPECT_EQ(source.size() * 2, hex.size());
404 EXPECT_EQ(source, decoded);
405
406 // we will now create a padded hex string, we want to explicitly allow
407 // decoding it this way also, ignoring spaces and colons between the numbers
408 hex.assign("00:ff 0f:f0");
410}
411
412TEST(ToHex, Array)
413{
414 EXPECT_EQ(
415 (std::array<char, 8>{{'f', 'f', 'a', 'b', '0', '1', '0', '0'}}),
416 (epee::to_hex::array(std::array<unsigned char, 4>{{0xFF, 0xAB, 0x01, 0x00}}))
417 );
418}
419
420TEST(ToHex, Ostream)
421{
422 std::stringstream out;
423 epee::to_hex::buffer(out, nullptr);
424 EXPECT_TRUE(out.str().empty());
425
426 {
427 const std::uint8_t source[] = {0xff, 0xab, 0x01, 0x00};
429 }
430
431 std::string expected{"ffab0100"};
432 EXPECT_EQ(expected, out.str());
433
434 const std::vector<unsigned char> all_bytes = get_all_bytes();
435
436 expected.append(std_to_hex(all_bytes));
437 epee::to_hex::buffer(out, epee::to_span(all_bytes));
438 EXPECT_EQ(expected, out.str());
439}
440
441TEST(ToHex, Formatted)
442{
443 std::stringstream out;
444 std::string expected{"<>"};
445
446 epee::to_hex::formatted(out, nullptr);
447 EXPECT_EQ(expected, out.str());
448
449 expected.append("<ffab0100>");
450 epee::to_hex::formatted(out, epee::as_byte_span("\xFF\xAB\x01"));
451 EXPECT_EQ(expected, out.str());
452
453 const std::vector<unsigned char> all_bytes = get_all_bytes();
454
455 expected.append("<").append(std_to_hex(all_bytes)).append(">");
456 epee::to_hex::formatted(out, epee::to_span(all_bytes));
457 EXPECT_EQ(expected, out.str());
458}
459
460TEST(StringTools, BuffToHex)
461{
462 const std::vector<unsigned char> all_bytes = get_all_bytes();
463
464 EXPECT_EQ(
465 std_to_hex(all_bytes),
467 std::string{reinterpret_cast<const char*>(all_bytes.data()), all_bytes.size()}
468 ))
469 );
470}
471
472TEST(StringTools, PodToHex)
473{
474 struct some_pod { unsigned char data[4]; };
475 EXPECT_EQ(
476 std::string{"ffab0100"},
477 (epee::string_tools::pod_to_hex(some_pod{{0xFF, 0xAB, 0x01, 0x00}}))
478 );
479}
480
481TEST(StringTools, ParseHex)
482{
483 static const char data[] = "a10b68c2";
484 for (size_t i = 0; i < sizeof(data); i += 2)
485 {
486 std::string res;
489 ASSERT_EQ(hex.size(), i);
490 ASSERT_EQ(memcmp(data, hex.data(), i), 0);
491 }
492}
493
494TEST(StringTools, ParseNotHex)
495{
496 std::string res;
497 for (size_t i = 0; i < 256; ++i)
498 {
499 std::string inputHexString = std::string(2, static_cast<char>(i));
500 if ((i >= '0' && i <= '9') || (i >= 'A' && i <= 'F') || (i >= 'a' && i <= 'f')) {
502 } else {
504 }
505 }
506
508}
509
510TEST(StringTools, GetIpString)
511{
512 EXPECT_EQ(
513 std::string{"0.0.0.0"}, epee::string_tools::get_ip_string_from_int32(0)
514 );
515 EXPECT_EQ(
516 std::string{"255.0.255.0"},
518 );
519 EXPECT_EQ(
520 std::string{"255.255.255.255"},
522 );
523}
524
525TEST(StringTools, GetIpInt32)
526{
527 std::uint32_t ip = 0;
534
536 EXPECT_EQ(htonl(1), ip);
537
539 EXPECT_EQ(htonl(0x1000001), ip);
540
542 EXPECT_EQ(htonl(0x1010001), ip);
543
545 EXPECT_EQ(0, ip);
546
548 EXPECT_EQ(htonl(0x01010101), ip);
549
550/*
551 The existing epee conversion function does not work with 255.255.255.255, for
552 the reasons specified in the inet_addr documentation. Consider fixing in a
553 future patch. This address is not likely to be used for purposes within
554 electroneum.
555 EXPECT_TRUE(epee::string_tools::get_ip_int32_from_string(ip, "255.255.255.255"));
556 EXPECT_EQ(htonl(0xffffffff), ip);
557*/
558
560 EXPECT_EQ(htonl(0xaff00ff), ip);
561
563 EXPECT_EQ(htonl(0xff0aff00), ip);
564}
565
566TEST(NetUtils, IPv4NetworkAddress)
567{
569
570 const auto ip1 = boost::endian::native_to_big(0x330012FFu);
571 const auto ip_loopback = boost::endian::native_to_big(0x7F000001u);
572 const auto ip_local = boost::endian::native_to_big(0x0A000000u);
573
574 epee::net_utils::ipv4_network_address address1{ip1, 65535};
575 CHECK_EQUAL(address1, address1);
576 EXPECT_STREQ("51.0.18.255:65535", address1.str().c_str());
577 EXPECT_STREQ("51.0.18.255", address1.host_str().c_str());
578 EXPECT_FALSE(address1.is_loopback());
579 EXPECT_FALSE(address1.is_local());
581 EXPECT_EQ(ip1, address1.ip());
582 EXPECT_EQ(65535, address1.port());
583 EXPECT_TRUE(epee::net_utils::ipv4_network_address{std::move(address1)} == address1);
585
586 const epee::net_utils::ipv4_network_address loopback{ip_loopback, 0};
587 CHECK_EQUAL(loopback, loopback);
588 CHECK_LESS_ENDIAN(address1, loopback);
589 EXPECT_STREQ("127.0.0.1:0", loopback.str().c_str());
590 EXPECT_STREQ("127.0.0.1", loopback.host_str().c_str());
591 EXPECT_TRUE(loopback.is_loopback());
592 EXPECT_FALSE(loopback.is_local());
594 EXPECT_EQ(ip_loopback, loopback.ip());
595 EXPECT_EQ(0, loopback.port());
596
597 const epee::net_utils::ipv4_network_address local{ip_local, 8080};
598 CHECK_EQUAL(local, local);
599 CHECK_LESS(local, address1);
600 CHECK_LESS(local, loopback);
601 EXPECT_FALSE(local.is_loopback());
602 EXPECT_TRUE(local.is_local());
603
605 CHECK_EQUAL(address2, address2);
606 CHECK_LESS_ENDIAN(address2, loopback);
607 CHECK_LESS(local, address2);
608 EXPECT_STREQ("51.0.18.255:55", address2.str().c_str());
609 EXPECT_STREQ("51.0.18.255", address2.host_str().c_str());
610
611
612 address2 = std::move(address1);
613 CHECK_EQUAL(address2, address1);
614
615 address2 = local;
616 CHECK_EQUAL(address2, local);
617 CHECK_LESS(address2, address1);
618
619 {
620 std::stringstream stream;
621 {
623 ostream << address1;
624 }
625 {
627 istream >> address2;
628 }
629 }
630 CHECK_EQUAL(address1, address2);
631 EXPECT_EQ(ip1, address2.ip());
632 EXPECT_EQ(65535, address2.port());
633}
634
635TEST(NetUtils, NetworkAddress)
636{
637 const auto ip1 = boost::endian::native_to_big(0x330012FFu);
638 const auto ip_loopback = boost::endian::native_to_big(0x7F000001u);
639 const auto ip_local = boost::endian::native_to_big(0x0A000000u);
640
641 struct custom_address {
642 constexpr static bool equal(const custom_address&) noexcept { return false; }
643 constexpr static bool less(const custom_address&) noexcept { return false; }
644 constexpr static bool is_same_host(const custom_address&) noexcept { return false; }
645 constexpr static bool is_loopback() noexcept { return false; }
646 constexpr static bool is_local() noexcept { return false; }
647 static std::string str() { return {}; }
648 static std::string host_str() { return {}; }
649 constexpr static epee::net_utils::address_type get_type_id() noexcept { return epee::net_utils::address_type(-1); }
650 constexpr static epee::net_utils::zone get_zone() noexcept { return epee::net_utils::zone::invalid; }
651 constexpr static bool is_blockable() noexcept { return false; }
652 };
653
655 CHECK_EQUAL(empty, empty);
656 EXPECT_TRUE(empty.is_same_host(empty));
657 EXPECT_STREQ("<none>", empty.str().c_str());
658 EXPECT_STREQ("<none>", empty.host_str().c_str());
659 EXPECT_FALSE(empty.is_loopback());
660 EXPECT_FALSE(empty.is_local());
662 //Temporary get_zone == public to support backwards compatibility with v0.11 nodes
663 EXPECT_EQ(epee::net_utils::zone::public_, empty.get_zone());
664 EXPECT_FALSE(empty.is_blockable());
665 EXPECT_THROW(empty.as<custom_address>(), std::bad_cast);
666
669 };
670 CHECK_EQUAL(address1, address1);
672 CHECK_LESS(empty, address1);
673 EXPECT_TRUE(address1.is_same_host(address1));
674 EXPECT_FALSE(empty.is_same_host(address1));
675 EXPECT_FALSE(address1.is_same_host(empty));
676 EXPECT_STREQ("51.0.18.255:65535", address1.str().c_str());
677 EXPECT_STREQ("51.0.18.255", address1.host_str().c_str());
678 EXPECT_FALSE(address1.is_loopback());
679 EXPECT_FALSE(address1.is_local());
682 EXPECT_TRUE(address1.is_blockable());
684 EXPECT_THROW(address1.as<custom_address>(), std::bad_cast);
685
688 };
689 CHECK_EQUAL(loopback, loopback);
690 CHECK_LESS(empty, loopback);
691 CHECK_LESS_ENDIAN(address1, loopback);
692 EXPECT_TRUE(loopback.is_same_host(loopback));
693 EXPECT_FALSE(loopback.is_same_host(address1));
694 EXPECT_FALSE(address1.is_same_host(loopback));
695 EXPECT_STREQ("127.0.0.1:0", loopback.str().c_str());
696 EXPECT_STREQ("127.0.0.1", loopback.host_str().c_str());
697 EXPECT_TRUE(loopback.is_loopback());
698 EXPECT_FALSE(loopback.is_local());
702
705 };
706 CHECK_EQUAL(local, local);
707 CHECK_LESS(local, loopback);
708 CHECK_LESS(local, address1);
709 EXPECT_FALSE(local.is_loopback());
710 EXPECT_TRUE(local.is_local());
711
714 };
715 CHECK_EQUAL(address2, address2);
716 CHECK_LESS(address2, address1);
717 CHECK_LESS(local, address2);
718 CHECK_LESS_ENDIAN(address2, loopback);
719 EXPECT_TRUE(address1.is_same_host(address2));
720 EXPECT_TRUE(address2.is_same_host(address1));
721 EXPECT_STREQ("51.0.18.255:55", address2.str().c_str());
722 EXPECT_STREQ("51.0.18.255", address2.host_str().c_str());
723
724 address2 = std::move(address1);
725 CHECK_EQUAL(address1, address1);
726 CHECK_EQUAL(empty, address1);
727 CHECK_LESS(address1, address2);
728 EXPECT_FALSE(address1.is_same_host(address2));
729 EXPECT_FALSE(address2.is_same_host(address1));
730 EXPECT_STREQ("51.0.18.255:65535", address2.str().c_str());
731 EXPECT_STREQ("51.0.18.255", address2.host_str().c_str());
732 EXPECT_FALSE(address1.is_loopback());
733 EXPECT_FALSE(address1.is_local());
734 EXPECT_THROW(address1.as<epee::net_utils::ipv4_network_address>(), std::bad_cast);
736
737 address2 = local;
738 CHECK_EQUAL(address2, local);
739 CHECK_LESS(address1, address2);
740 EXPECT_TRUE(address2.is_same_host(local));
741 EXPECT_TRUE(local.is_same_host(address2));
742 EXPECT_FALSE(address2.is_same_host(address1));
743 EXPECT_FALSE(address1.is_same_host(address2));
744
745 {
746 std::stringstream stream;
747 {
749 ostream << address2;
750 }
751 {
753 istream >> address1;
754 }
755 }
756 CHECK_EQUAL(address1, address2);
757 EXPECT_TRUE(address1.is_same_host(address2));
758 EXPECT_TRUE(address2.is_same_host(address1));
760
761 address1 = custom_address{};
762 CHECK_EQUAL(address1, address1);
763 CHECK_LESS(address2, address1);
764 EXPECT_FALSE(address1.is_same_host(loopback));
765 EXPECT_FALSE(loopback.is_same_host(address1));
766 EXPECT_THROW(address1.as<epee::net_utils::ipv4_network_address>(), std::bad_cast);
767 EXPECT_NO_THROW(address1.as<custom_address>());
768}
769
770static bool is_local(const char *s)
771{
772 uint32_t ip;
773 CHECK_AND_ASSERT_THROW_MES(epee::string_tools::get_ip_int32_from_string(ip, s), std::string("Invalid IP address: ") + s);
775}
776
777TEST(NetUtils, PrivateRanges)
778{
779 ASSERT_EQ(is_local("10.0.0.0"), true);
780 ASSERT_EQ(is_local("10.255.0.0"), true);
781 ASSERT_EQ(is_local("127.0.0.0"), false); // loopback is not considered local
782 ASSERT_EQ(is_local("192.167.255.255"), false);
783 ASSERT_EQ(is_local("192.168.0.0"), true);
784 ASSERT_EQ(is_local("192.168.255.255"), true);
785 ASSERT_EQ(is_local("192.169.0.0"), false);
786 ASSERT_EQ(is_local("172.0.0.0"), false);
787 ASSERT_EQ(is_local("172.15.255.255"), false);
788 ASSERT_EQ(is_local("172.16.0.0"), true);
789 ASSERT_EQ(is_local("172.16.255.255"), true);
790 ASSERT_EQ(is_local("172.31.255.255"), true);
791 ASSERT_EQ(is_local("172.32.0.0"), false);
792 ASSERT_EQ(is_local("0.0.0.0"), false);
793 ASSERT_EQ(is_local("255.255.255.254"), false);
794 ASSERT_EQ(is_local("11.255.255.255"), false);
795 ASSERT_EQ(is_local("0.0.0.10"), false);
796 ASSERT_EQ(is_local("0.0.168.192"), false);
797 ASSERT_EQ(is_local("0.0.30.172"), false);
798 ASSERT_EQ(is_local("0.0.30.127"), false);
799}
800
801TEST(net_buffer, basic)
802{
804
805 ASSERT_EQ(buf.size(), 0);
806 EXPECT_THROW(buf.span(1), std::runtime_error);
807 buf.append("a", 1);
808 epee::span<const uint8_t> span = buf.span(1);
809 ASSERT_EQ(span.size(), 1);
810 ASSERT_EQ(span.data()[0], 'a');
811 EXPECT_THROW(buf.span(2), std::runtime_error);
812 buf.append("bc", 2);
813 buf.erase(1);
814 EXPECT_THROW(buf.span(3), std::runtime_error);
815 span = buf.span(2);
816 ASSERT_EQ(span.size(), 2);
817 ASSERT_EQ(span.data()[0], 'b');
818 ASSERT_EQ(span.data()[1], 'c');
819 buf.erase(1);
820 EXPECT_THROW(buf.span(2), std::runtime_error);
821 span = buf.span(1);
822 ASSERT_EQ(span.size(), 1);
823 ASSERT_EQ(span.data()[0], 'c');
824 EXPECT_THROW(buf.erase(2), std::runtime_error);
825 buf.erase(1);
826 EXPECT_EQ(buf.size(), 0);
827 EXPECT_THROW(buf.span(1), std::runtime_error);
828}
829
830TEST(net_buffer, existing_capacity)
831{
833
834 buf.append("123456789", 9);
835 buf.erase(9);
836 buf.append("abc", 3);
837 buf.append("def", 3);
838 ASSERT_EQ(buf.size(), 6);
839 epee::span<const uint8_t> span = buf.span(6);
840 ASSERT_TRUE(!memcmp(span.data(), "abcdef", 6));
841}
842
843TEST(net_buffer, reallocate)
844{
846
847 buf.append(std::string(4000, ' ').c_str(), 4000);
848 buf.append(std::string(8000, '0').c_str(), 8000);
849 ASSERT_EQ(buf.size(), 12000);
850 epee::span<const uint8_t> span = buf.span(12000);
851 ASSERT_TRUE(!memcmp(span.data(), std::string(4000, ' ').c_str(), 4000));
852 ASSERT_TRUE(!memcmp(span.data() + 4000, std::string(8000, '0').c_str(), 8000));
853}
854
855TEST(net_buffer, move)
856{
858
859 buf.append(std::string(400, ' ').c_str(), 400);
860 buf.erase(399);
861 buf.append(std::string(4000, '0').c_str(), 4000);
862 ASSERT_EQ(buf.size(), 4001);
863 epee::span<const uint8_t> span = buf.span(4001);
864 ASSERT_TRUE(!memcmp(span.data(), std::string(1, ' ').c_str(), 1));
865 ASSERT_TRUE(!memcmp(span.data() + 1, std::string(4000, '0').c_str(), 4000));
866}
867
868TEST(parsing, isspace)
869{
871 for (int c = 1; c < 256; ++c)
872 {
873 ASSERT_EQ(epee::misc_utils::parse::isspace(c), strchr("\r\n\t\f\v ", c) != NULL);
874 }
875}
876
877TEST(parsing, isdigit)
878{
880 for (int c = 1; c < 256; ++c)
881 {
882 ASSERT_EQ(epee::misc_utils::parse::isdigit(c), strchr("0123456789", c) != NULL);
883 }
884}
885
886TEST(parsing, number)
887{
888 boost::string_ref val;
889 std::string s;
890 std::string::const_iterator i;
891
892 // the parser expects another character to end the number, and accepts things
893 // that aren't numbers, as it's meant as a pre-filter for strto* functions,
894 // so we just check that numbers get accepted, but don't test non numbers
895
896 s = "0 ";
897 i = s.begin();
899 ASSERT_EQ(val, "0");
900
901 s = "000 ";
902 i = s.begin();
904 ASSERT_EQ(val, "000");
905
906 s = "10x";
907 i = s.begin();
909 ASSERT_EQ(val, "10");
910
911 s = "10.09/";
912 i = s.begin();
914 ASSERT_EQ(val, "10.09");
915
916 s = "-1.r";
917 i = s.begin();
919 ASSERT_EQ(val, "-1.");
920
921 s = "-49.;";
922 i = s.begin();
924 ASSERT_EQ(val, "-49.");
925
926 s = "0.78/";
927 i = s.begin();
929 ASSERT_EQ(val, "0.78");
930
931 s = "33E9$";
932 i = s.begin();
934 ASSERT_EQ(val, "33E9");
935
936 s = ".34e2=";
937 i = s.begin();
939 ASSERT_EQ(val, ".34e2");
940
941 s = "-9.34e-2=";
942 i = s.begin();
944 ASSERT_EQ(val, "-9.34e-2");
945
946 s = "+9.34e+03=";
947 i = s.begin();
949 ASSERT_EQ(val, "+9.34e+03");
950}
static constexpr address_type get_type_id() noexcept
constexpr uint16_t port() const noexcept
constexpr uint32_t ip() const noexcept
bool is_same_host(const network_address &other) const
Non-owning sequence of data. Does not deep copy.
Definition span.h:57
const T & const_reference
Definition span.h:74
constexpr const_iterator cend() const noexcept
Definition span.h:107
constexpr std::size_t size_bytes() const noexcept
Definition span.h:112
constexpr iterator end() const noexcept
Definition span.h:106
constexpr std::size_t size() const noexcept
Definition span.h:111
const T * const_pointer
Definition span.h:72
std::ptrdiff_t difference_type
Definition span.h:70
pointer iterator
Definition span.h:75
T value_type
Definition span.h:68
constexpr const_iterator cbegin() const noexcept
Definition span.h:104
const_pointer const_iterator
Definition span.h:76
T * pointer
Definition span.h:71
constexpr bool empty() const noexcept
Definition span.h:109
constexpr iterator begin() const noexcept
Definition span.h:103
constexpr pointer data() const noexcept
Definition span.h:110
T & reference
Definition span.h:73
std::size_t size_type
Definition span.h:69
#define CHECK_LESS(lhs, rhs)
#define CHECK_LESS_ENDIAN(lhs, rhs)
#define CHECK_EQUAL(lhs, rhs)
#define ASSERT_EQ(val1, val2)
Definition gtest.h:1956
#define EXPECT_NO_THROW(statement)
Definition gtest.h:1845
#define EXPECT_EQ(val1, val2)
Definition gtest.h:1922
#define EXPECT_THROW(statement, expected_exception)
Definition gtest.h:1843
#define ASSERT_FALSE(condition)
Definition gtest.h:1868
#define EXPECT_TRUE(condition)
Definition gtest.h:1859
#define EXPECT_STREQ(s1, s2)
Definition gtest.h:1995
#define TEST(test_case_name, test_name)
Definition gtest.h:2187
#define ASSERT_TRUE(condition)
Definition gtest.h:1865
#define EXPECT_FALSE(condition)
Definition gtest.h:1862
const char * res
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
bool match_number(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, boost::string_ref &val)
bool is_ip_local(uint32_t ip)
Definition local_ip.h:35
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
std::string pod_to_hex(const t_pod_type &s)
std::string get_ip_string_from_int32(uint32_t ip)
bool get_ip_int32_from_string(uint32_t &ip, const std::string &ip_str)
std::string buff_to_hex_nodelimer(const std::string &src)
span< std::uint8_t > as_mut_byte_span(T &src) noexcept
Definition span.h:162
span< const std::uint8_t > to_byte_span(const span< const T > src) noexcept
Definition span.h:145
constexpr span< const typename T::value_type > to_span(const T &src)
Definition span.h:123
span< const std::uint8_t > as_byte_span(const T &src) noexcept
Definition span.h:153
constexpr span< typename T::value_type > to_mut_span(T &src)
Definition span.h:131
mdb_size_t count(MDB_cursor *cur)
const GenericPointer< typename T::ValueType > T2 value
Definition pointer.h:1225
const CharType(& source)[N]
Definition pointer.h:1147
const char * buf
unsigned int uint32_t
Definition stdint.h:126
static std::vector< uint8_t > vector(boost::string_ref src)
Definition hex.cpp:88
static std::array< char, N *2 > array(const std::array< std::uint8_t, N > &src) noexcept
Definition hex.h:53
static std::string string(const span< const std::uint8_t > src)
Definition hex.cpp:68
static void formatted(std::ostream &out, const span< const std::uint8_t > src)
Append < + src + > as hex to out.
Definition hex.cpp:76
static void buffer(std::ostream &out, const span< const std::uint8_t > src)
Append src as hex to out.
Definition hex.cpp:71