Electroneum
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 
56 namespace
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 
146 TEST(Span, Traits)
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 
169 TEST(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 
201 TEST(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 
236 TEST(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 
257  EXPECT_TRUE(noexcept(epee::span<char>(epee::span<char>(lvalue))));
258  EXPECT_TRUE(noexcept(lvalue = lvalue));
259  EXPECT_TRUE(noexcept(lvalue = clvalue));
260  EXPECT_TRUE(noexcept(lvalue = epee::span<char>(lvalue)));
261 }
262 
263 TEST(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 
278 TEST(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 
301 TEST(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 
320 TEST(Span, ToByteSpan)
321 {
322  const char expected[] = {56, 44, 11, 5};
323  EXPECT_TRUE(
324  boost::range::equal(
325  std::array<std::uint8_t, 4>{{56, 44, 11, 5}},
326  epee::to_byte_span<char>(expected)
327  )
328  );
329  EXPECT_TRUE(
330  boost::range::equal(
331  std::array<char, 4>{{56, 44, 11, 5}},
333  )
334  );
335 }
336 
337 TEST(Span, AsByteSpan)
338 {
339  struct some_pod { char value[4]; };
340  const some_pod immutable {{ 5, 10, 12, 127 }};
341  EXPECT_TRUE(
342  boost::range::equal(
343  std::array<unsigned char, 4>{{5, 10, 12, 127}},
344  epee::as_byte_span(immutable)
345  )
346  );
347  EXPECT_TRUE(
348  boost::range::equal(
349  std::array<std::uint8_t, 3>{{'a', 'y', 0x00}}, epee::as_byte_span("ay")
350  )
351  );
352 }
353 
354 TEST(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);
361  EXPECT_TRUE(
362  boost::range::equal(
363  std::array<unsigned char, 4>{{1, 2, 3, 4}}, actual.value
364  )
365  );
366 }
367 
368 TEST(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 
378 TEST(ToHex, String)
379 {
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 
393 TEST(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 
412 TEST(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 
420 TEST(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 
441 TEST(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 
460 TEST(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 
472 TEST(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 
481 TEST(StringTools, ParseHex)
482 {
483  static const char data[] = "a10b68c2";
484  for (size_t i = 0; i < sizeof(data); i += 2)
485  {
489  ASSERT_EQ(hex.size(), i);
490  ASSERT_EQ(memcmp(data, hex.data(), i), 0);
491  }
492 }
493 
494 TEST(StringTools, ParseNotHex)
495 {
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 
510 TEST(StringTools, GetIpString)
511 {
512  EXPECT_EQ(
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 
525 TEST(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 
566 TEST(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());
584  EXPECT_TRUE(epee::net_utils::ipv4_network_address{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 
604  epee::net_utils::ipv4_network_address address2{ip1, 55};
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 
635 TEST(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 
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
664  EXPECT_FALSE(empty.is_blockable());
665  EXPECT_THROW(empty.as<custom_address>(), std::bad_cast);
666 
669  };
670  CHECK_EQUAL(address1, address1);
671  CHECK_EQUAL(epee::net_utils::network_address{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());
681  EXPECT_EQ(epee::net_utils::zone::public_, address1.get_zone());
682  EXPECT_TRUE(address1.is_blockable());
684  EXPECT_THROW(address1.as<custom_address>(), std::bad_cast);
685 
686  const epee::net_utils::network_address loopback{
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());
700  EXPECT_EQ(epee::net_utils::zone::public_, address1.get_zone());
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 
770 static bool is_local(const char *s)
771 {
772  uint32_t ip;
775 }
776 
777 TEST(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 
801 TEST(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 
830 TEST(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 
843 TEST(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 
855 TEST(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 
868 TEST(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 
877 TEST(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 
886 TEST(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();
898  epee::misc_utils::parse::match_number(i, s.end(), val);
899  ASSERT_EQ(val, "0");
900 
901  s = "000 ";
902  i = s.begin();
903  epee::misc_utils::parse::match_number(i, s.end(), val);
904  ASSERT_EQ(val, "000");
905 
906  s = "10x";
907  i = s.begin();
908  epee::misc_utils::parse::match_number(i, s.end(), val);
909  ASSERT_EQ(val, "10");
910 
911  s = "10.09/";
912  i = s.begin();
913  epee::misc_utils::parse::match_number(i, s.end(), val);
914  ASSERT_EQ(val, "10.09");
915 
916  s = "-1.r";
917  i = s.begin();
918  epee::misc_utils::parse::match_number(i, s.end(), val);
919  ASSERT_EQ(val, "-1.");
920 
921  s = "-49.;";
922  i = s.begin();
923  epee::misc_utils::parse::match_number(i, s.end(), val);
924  ASSERT_EQ(val, "-49.");
925 
926  s = "0.78/";
927  i = s.begin();
928  epee::misc_utils::parse::match_number(i, s.end(), val);
929  ASSERT_EQ(val, "0.78");
930 
931  s = "33E9$";
932  i = s.begin();
933  epee::misc_utils::parse::match_number(i, s.end(), val);
934  ASSERT_EQ(val, "33E9");
935 
936  s = ".34e2=";
937  i = s.begin();
938  epee::misc_utils::parse::match_number(i, s.end(), val);
939  ASSERT_EQ(val, ".34e2");
940 
941  s = "-9.34e-2=";
942  i = s.begin();
943  epee::misc_utils::parse::match_number(i, s.end(), val);
944  ASSERT_EQ(val, "-9.34e-2");
945 
946  s = "+9.34e+03=";
947  i = s.begin();
948  epee::misc_utils::parse::match_number(i, s.end(), val);
949  ASSERT_EQ(val, "+9.34e+03");
950 }
const char * res
Definition: hmac_keccak.cpp:41
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
std::size_t size_type
Definition: span.h:69
const CharType(& source)[N]
Definition: pointer.h:1147
#define EXPECT_NO_THROW(statement)
Definition: gtest.h:1845
span< const std::uint8_t > as_byte_span(const T &src) noexcept
Definition: span.h:153
TEST(Span, Traits)
Definition: epee_utils.cpp:146
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
T & reference
Definition: span.h:73
#define EXPECT_STREQ(s1, s2)
Definition: gtest.h:1995
::std::string string
Definition: gtest-port.h:1097
constexpr const_iterator cbegin() const noexcept
Definition: span.h:104
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
static std::array< char, N *2 > array(const std::array< std::uint8_t, N > &src) noexcept
Definition: hex.h:53
const T * const_pointer
Definition: span.h:72
span< std::uint8_t > as_mut_byte_span(T &src) noexcept
Definition: span.h:162
Non-owning sequence of data. Does not deep copy.
Definition: span.h:56
#define CHECK_LESS_ENDIAN(lhs, rhs)
Definition: epee_utils.cpp:142
unsigned char uint8_t
Definition: stdint.h:124
T value_type
Definition: span.h:68
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
constexpr std::size_t size() const noexcept
Definition: span.h:111
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
constexpr span< typename T::value_type > to_mut_span(T &src)
Definition: span.h:131
std::string get_ip_string_from_int32(uint32_t ip)
mdb_size_t count(MDB_cursor *cur)
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
#define CHECK_EQUAL(lhs, rhs)
Definition: epee_utils.cpp:111
constexpr const_iterator cend() const noexcept
Definition: span.h:107
static std::vector< uint8_t > vector(boost::string_ref src)
Definition: hex.cpp:88
unsigned int uint32_t
Definition: stdint.h:126
::std::wstring wstring
Definition: gtest-port.h:1103
const_pointer const_iterator
Definition: span.h:76
int less(MDB_val const *left, MDB_val const *right) noexcept
Definition: util.h:111
static constexpr address_type get_type_id() noexcept
const char * buf
Definition: slow_memmem.cpp:74
constexpr iterator end() const noexcept
Definition: span.h:106
boost::endian::big_uint32_t ip
Definition: socks.cpp:61
bool is_ip_local(uint32_t ip)
Definition: local_ip.h:35
constexpr span< const typename T::value_type > to_span(const T &src)
Definition: span.h:123
const T & move(const T &t)
Definition: gtest-port.h:1317
std::string buff_to_hex_nodelimer(const std::string &src)
Definition: string_tools.h:87
static void buffer(std::ostream &out, const span< const std::uint8_t > src)
Append src as hex to out.
Definition: hex.cpp:71
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
const T & const_reference
Definition: span.h:74
static std::string string(const span< const std::uint8_t > src)
Definition: hex.cpp:68
#define CHECK_LESS(lhs, rhs)
Definition: epee_utils.cpp:125
constexpr iterator begin() const noexcept
Definition: span.h:103
constexpr std::size_t size_bytes() const noexcept
Definition: span.h:112
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
bool match_number(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, boost::string_ref &val)
constexpr bool empty() const noexcept
Definition: span.h:109
T * pointer
Definition: span.h:71
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Definition: string_tools.h:92
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static void formatted(std::ostream &out, const span< const std::uint8_t > src)
Append < + src + > as hex to out.
Definition: hex.cpp:76
std::ptrdiff_t difference_type
Definition: span.h:70
pointer iterator
Definition: span.h:75
bool get_ip_int32_from_string(uint32_t &ip, const std::string &ip_str)
span< const std::uint8_t > to_byte_span(const span< const T > src) noexcept
Definition: span.h:145
constexpr pointer data() const noexcept
Definition: span.h:110