diff options
author | Lee Clagett <code@leeclagett.com> | 2019-05-16 16:34:22 -0400 |
---|---|---|
committer | Lee Clagett <code@leeclagett.com> | 2019-07-17 14:22:37 +0000 |
commit | 3b24b1d082da28da15dc5e3aeaa0ebebe7758f2f (patch) | |
tree | 04c19819bc99545f0472be8812c850ed1a433bfa /tests/unit_tests/net.cpp | |
parent | Add ref-counted buffer byte_slice. Currently used for sending TCP data. (diff) | |
download | monero-3b24b1d082da28da15dc5e3aeaa0ebebe7758f2f.tar.xz |
Added support for "noise" over I1P/Tor to mask Tx transmission.
Diffstat (limited to 'tests/unit_tests/net.cpp')
-rw-r--r-- | tests/unit_tests/net.cpp | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/tests/unit_tests/net.cpp b/tests/unit_tests/net.cpp index 3acf75f3b..f24ffb45c 100644 --- a/tests/unit_tests/net.cpp +++ b/tests/unit_tests/net.cpp @@ -26,6 +26,7 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include <algorithm> #include <atomic> #include <boost/archive/portable_binary_oarchive.hpp> #include <boost/archive/portable_binary_iarchive.hpp> @@ -36,13 +37,22 @@ #include <boost/asio/steady_timer.hpp> #include <boost/asio/write.hpp> #include <boost/endian/conversion.hpp> +#include <boost/range/adaptor/sliced.hpp> +#include <boost/range/combine.hpp> #include <boost/system/error_code.hpp> #include <boost/thread/thread.hpp> +#include <boost/uuid/nil_generator.hpp> +#include <boost/uuid/random_generator.hpp> +#include <boost/uuid/uuid.hpp> +#include <cstdint> #include <cstring> #include <functional> #include <gtest/gtest.h> +#include <map> #include <memory> +#include <type_traits> +#include "net/dandelionpp.h" #include "net/error.h" #include "net/net_utils_base.h" #include "net/socks.h" @@ -857,3 +867,389 @@ TEST(socks_connector, timeout) EXPECT_THROW(sock.get().is_open(), boost::system::system_error); } +TEST(dandelionpp_map, traits) +{ + EXPECT_TRUE(std::is_default_constructible<net::dandelionpp::connection_map>()); + EXPECT_TRUE(std::is_move_constructible<net::dandelionpp::connection_map>()); + EXPECT_TRUE(std::is_move_assignable<net::dandelionpp::connection_map>()); + EXPECT_FALSE(std::is_copy_constructible<net::dandelionpp::connection_map>()); + EXPECT_FALSE(std::is_copy_assignable<net::dandelionpp::connection_map>()); +} + +TEST(dandelionpp_map, empty) +{ + const net::dandelionpp::connection_map mapper{}; + + EXPECT_EQ(mapper.begin(), mapper.end()); + EXPECT_EQ(0u, mapper.size()); + + const net::dandelionpp::connection_map cloned = mapper.clone(); + EXPECT_EQ(cloned.begin(), cloned.end()); + EXPECT_EQ(0u, cloned.size()); +} + +TEST(dandelionpp_map, zero_stems) +{ + std::vector<boost::uuids::uuid> connections{6}; + std::generate(connections.begin(), connections.end(), boost::uuids::random_generator{}); + + net::dandelionpp::connection_map mapper{connections, 0}; + EXPECT_EQ(mapper.begin(), mapper.end()); + EXPECT_EQ(0u, mapper.size()); + + for (const boost::uuids::uuid& connection : connections) + EXPECT_TRUE(mapper.get_stem(connection).is_nil()); + + EXPECT_FALSE(mapper.update(connections)); + EXPECT_EQ(mapper.begin(), mapper.end()); + EXPECT_EQ(0u, mapper.size()); + + for (const boost::uuids::uuid& connection : connections) + EXPECT_TRUE(mapper.get_stem(connection).is_nil()); + + const net::dandelionpp::connection_map cloned = mapper.clone(); + EXPECT_EQ(cloned.end(), cloned.begin()); + EXPECT_EQ(0u, cloned.size()); +} + +TEST(dandelionpp_map, dropped_connection) +{ + std::vector<boost::uuids::uuid> connections{6}; + std::generate(connections.begin(), connections.end(), boost::uuids::random_generator{}); + std::sort(connections.begin(), connections.end()); + + // select 3 of 6 outgoing connections + net::dandelionpp::connection_map mapper{connections, 3}; + EXPECT_EQ(3u, mapper.size()); + EXPECT_EQ(3, mapper.end() - mapper.begin()); + { + std::set<boost::uuids::uuid> used; + for (const boost::uuids::uuid& connection : mapper) + { + EXPECT_TRUE(used.insert(connection).second); + EXPECT_TRUE(std::binary_search(connections.begin(), connections.end(), connection)); + } + } + { + const net::dandelionpp::connection_map cloned = mapper.clone(); + EXPECT_EQ(3u, cloned.size()); + ASSERT_EQ(mapper.end() - mapper.begin(), cloned.end() - cloned.begin()); + for (auto elem : boost::combine(mapper, cloned)) + EXPECT_EQ(boost::get<0>(elem), boost::get<1>(elem)); + } + EXPECT_FALSE(mapper.update(connections)); + EXPECT_EQ(3u, mapper.size()); + ASSERT_EQ(3, mapper.end() - mapper.begin()); + { + std::set<boost::uuids::uuid> used; + for (const boost::uuids::uuid& connection : mapper) + { + EXPECT_FALSE(connection.is_nil()); + EXPECT_TRUE(used.insert(connection).second); + EXPECT_TRUE(std::binary_search(connections.begin(), connections.end(), connection)); + } + } + std::map<boost::uuids::uuid, boost::uuids::uuid> mapping; + std::vector<boost::uuids::uuid> in_connections{9}; + std::generate(in_connections.begin(), in_connections.end(), boost::uuids::random_generator{}); + { + std::map<boost::uuids::uuid, std::size_t> used; + std::multimap<boost::uuids::uuid, boost::uuids::uuid> inverse_mapping; + for (const boost::uuids::uuid& connection : in_connections) + { + const boost::uuids::uuid out = mapper.get_stem(connection); + EXPECT_FALSE(out.is_nil()); + EXPECT_TRUE(mapping.emplace(connection, out).second); + inverse_mapping.emplace(out, connection); + used[out]++; + } + + EXPECT_EQ(3u, used.size()); + for (const std::pair<boost::uuids::uuid, std::size_t>& entry : used) + EXPECT_EQ(3u, entry.second); + + for (const boost::uuids::uuid& connection : in_connections) + EXPECT_EQ(mapping[connection], mapper.get_stem(connection)); + + // drop 1 connection, and select replacement from 1 of unused 3. + const boost::uuids::uuid lost_connection = *(++mapper.begin()); + const auto elem = std::lower_bound(connections.begin(), connections.end(), lost_connection); + ASSERT_NE(connections.end(), elem); + ASSERT_EQ(lost_connection, *elem); + connections.erase(elem); + + EXPECT_TRUE(mapper.update(connections)); + EXPECT_EQ(3u, mapper.size()); + ASSERT_EQ(3, mapper.end() - mapper.begin()); + + for (const boost::uuids::uuid& connection : mapper) + { + EXPECT_FALSE(connection.is_nil()); + EXPECT_NE(lost_connection, connection); + } + + const boost::uuids::uuid newly_mapped = *(++mapper.begin()); + EXPECT_FALSE(newly_mapped.is_nil()); + EXPECT_NE(lost_connection, newly_mapped); + + for (auto elems = inverse_mapping.equal_range(lost_connection); elems.first != elems.second; ++elems.first) + mapping[elems.first->second] = newly_mapped; + } + { + const net::dandelionpp::connection_map cloned = mapper.clone(); + EXPECT_EQ(3u, cloned.size()); + ASSERT_EQ(mapper.end() - mapper.begin(), cloned.end() - cloned.begin()); + for (auto elem : boost::combine(mapper, cloned)) + EXPECT_EQ(boost::get<0>(elem), boost::get<1>(elem)); + } + // mappings should remain evenly distributed amongst 2, with 3 sitting in waiting + { + std::set<boost::uuids::uuid> used; + for (const boost::uuids::uuid& connection : mapper) + { + EXPECT_FALSE(connection.is_nil()); + EXPECT_TRUE(used.insert(connection).second); + EXPECT_TRUE(std::binary_search(connections.begin(), connections.end(), connection)); + } + } + { + std::map<boost::uuids::uuid, std::size_t> used; + for (const boost::uuids::uuid& connection : in_connections) + { + const boost::uuids::uuid& out = mapper.get_stem(connection); + EXPECT_FALSE(out.is_nil()); + EXPECT_EQ(mapping[connection], out); + used[out]++; + } + + EXPECT_EQ(3u, used.size()); + for (const std::pair<boost::uuids::uuid, std::size_t>& entry : used) + EXPECT_EQ(3u, entry.second); + } + { + const net::dandelionpp::connection_map cloned = mapper.clone(); + EXPECT_EQ(3u, cloned.size()); + ASSERT_EQ(mapper.end() - mapper.begin(), cloned.end() - cloned.begin()); + for (auto elem : boost::combine(mapper, cloned)) + EXPECT_EQ(boost::get<0>(elem), boost::get<1>(elem)); + } +} + +TEST(dandelionpp_map, dropped_connection_remapped) +{ + boost::uuids::random_generator random_uuid{}; + + std::vector<boost::uuids::uuid> connections{3}; + std::generate(connections.begin(), connections.end(), random_uuid); + std::sort(connections.begin(), connections.end()); + + // select 3 of 3 outgoing connections + net::dandelionpp::connection_map mapper{connections, 3}; + EXPECT_EQ(3u, mapper.size()); + EXPECT_EQ(3, mapper.end() - mapper.begin()); + { + std::set<boost::uuids::uuid> used; + for (const boost::uuids::uuid& connection : mapper) + { + EXPECT_FALSE(connection.is_nil()); + EXPECT_TRUE(used.insert(connection).second); + EXPECT_TRUE(std::binary_search(connections.begin(), connections.end(), connection)); + } + } + EXPECT_FALSE(mapper.update(connections)); + EXPECT_EQ(3u, mapper.size()); + ASSERT_EQ(3, mapper.end() - mapper.begin()); + { + std::set<boost::uuids::uuid> used; + for (const boost::uuids::uuid& connection : mapper) + { + EXPECT_FALSE(connection.is_nil()); + EXPECT_TRUE(used.insert(connection).second); + EXPECT_TRUE(std::binary_search(connections.begin(), connections.end(), connection)); + } + } + std::map<boost::uuids::uuid, boost::uuids::uuid> mapping; + std::vector<boost::uuids::uuid> in_connections{9}; + std::generate(in_connections.begin(), in_connections.end(), random_uuid); + { + std::map<boost::uuids::uuid, std::size_t> used; + std::multimap<boost::uuids::uuid, boost::uuids::uuid> inverse_mapping; + for (const boost::uuids::uuid& connection : in_connections) + { + const boost::uuids::uuid out = mapper.get_stem(connection); + EXPECT_FALSE(out.is_nil()); + EXPECT_TRUE(mapping.emplace(connection, out).second); + inverse_mapping.emplace(out, connection); + used[out]++; + } + + EXPECT_EQ(3u, used.size()); + for (const std::pair<boost::uuids::uuid, std::size_t>& entry : used) + EXPECT_EQ(3u, entry.second); + + for (const boost::uuids::uuid& connection : in_connections) + EXPECT_EQ(mapping[connection], mapper.get_stem(connection)); + + // drop 1 connection leaving "hole" + const boost::uuids::uuid lost_connection = *(++mapper.begin()); + const auto elem = std::lower_bound(connections.begin(), connections.end(), lost_connection); + ASSERT_NE(connections.end(), elem); + ASSERT_EQ(lost_connection, *elem); + connections.erase(elem); + + EXPECT_TRUE(mapper.update(connections)); + EXPECT_EQ(2u, mapper.size()); + EXPECT_EQ(3, mapper.end() - mapper.begin()); + + for (auto elems = inverse_mapping.equal_range(lost_connection); elems.first != elems.second; ++elems.first) + mapping[elems.first->second] = boost::uuids::nil_uuid(); + } + // remap 3 connections and map 1 new connection to 2 remaining out connections + in_connections.resize(10); + in_connections[9] = random_uuid(); + { + std::map<boost::uuids::uuid, std::size_t> used; + for (const boost::uuids::uuid& connection : in_connections) + { + const boost::uuids::uuid& out = mapper.get_stem(connection); + EXPECT_FALSE(out.is_nil()); + used[out]++; + + boost::uuids::uuid& expected = mapping[connection]; + if (!expected.is_nil()) + EXPECT_EQ(expected, out); + else + expected = out; + } + + EXPECT_EQ(2u, used.size()); + for (const std::pair<boost::uuids::uuid, std::size_t>& entry : used) + EXPECT_EQ(5u, entry.second); + } + // select 3 of 3 connections but do not remap existing links + connections.resize(3); + connections[2] = random_uuid(); + EXPECT_TRUE(mapper.update(connections)); + EXPECT_EQ(3u, mapper.size()); + EXPECT_EQ(3, mapper.end() - mapper.begin()); + { + std::map<boost::uuids::uuid, std::size_t> used; + for (const boost::uuids::uuid& connection : in_connections) + { + const boost::uuids::uuid& out = mapper.get_stem(connection); + EXPECT_FALSE(out.is_nil()); + used[out]++; + + EXPECT_EQ(mapping[connection], out); + } + + EXPECT_EQ(2u, used.size()); + for (const std::pair<boost::uuids::uuid, std::size_t>& entry : used) + EXPECT_EQ(5u, entry.second); + } + // map 8 new incoming connections across 3 outgoing links + in_connections.resize(18); + std::generate(in_connections.begin() + 10, in_connections.end(), random_uuid); + { + std::map<boost::uuids::uuid, std::size_t> used; + for (const boost::uuids::uuid& connection : in_connections) + { + const boost::uuids::uuid& out = mapper.get_stem(connection); + EXPECT_FALSE(out.is_nil()); + used[out]++; + + boost::uuids::uuid& expected = mapping[connection]; + if (!expected.is_nil()) + EXPECT_EQ(expected, out); + else + expected = out; + } + + EXPECT_EQ(3u, used.size()); + for (const std::pair<boost::uuids::uuid, std::size_t>& entry : used) + EXPECT_EQ(6u, entry.second); + } +} + +TEST(dandelionpp_map, dropped_all_connections) +{ + boost::uuids::random_generator random_uuid{}; + + std::vector<boost::uuids::uuid> connections{8}; + std::generate(connections.begin(), connections.end(), random_uuid); + std::sort(connections.begin(), connections.end()); + + // select 3 of 8 outgoing connections + net::dandelionpp::connection_map mapper{connections, 3}; + EXPECT_EQ(3u, mapper.size()); + EXPECT_EQ(3, mapper.end() - mapper.begin()); + { + std::set<boost::uuids::uuid> used; + for (const boost::uuids::uuid& connection : mapper) + { + EXPECT_FALSE(connection.is_nil()); + EXPECT_TRUE(used.insert(connection).second); + EXPECT_TRUE(std::binary_search(connections.begin(), connections.end(), connection)); + } + } + EXPECT_FALSE(mapper.update(connections)); + EXPECT_EQ(3u, mapper.size()); + ASSERT_EQ(3, mapper.end() - mapper.begin()); + { + std::set<boost::uuids::uuid> used; + for (const boost::uuids::uuid& connection : mapper) + { + EXPECT_FALSE(connection.is_nil()); + EXPECT_TRUE(used.insert(connection).second); + EXPECT_TRUE(std::binary_search(connections.begin(), connections.end(), connection)); + } + } + std::vector<boost::uuids::uuid> in_connections{9}; + std::generate(in_connections.begin(), in_connections.end(), random_uuid); + { + std::map<boost::uuids::uuid, std::size_t> used; + std::map<boost::uuids::uuid, boost::uuids::uuid> mapping; + for (const boost::uuids::uuid& connection : in_connections) + { + const boost::uuids::uuid out = mapper.get_stem(connection); + EXPECT_FALSE(out.is_nil()); + EXPECT_TRUE(mapping.emplace(connection, out).second); + used[out]++; + } + + EXPECT_EQ(3u, used.size()); + for (const std::pair<boost::uuids::uuid, std::size_t>& entry : used) + EXPECT_EQ(3u, entry.second); + + for (const boost::uuids::uuid& connection : in_connections) + EXPECT_EQ(mapping[connection], mapper.get_stem(connection)); + + // drop all connections + connections.clear(); + + EXPECT_TRUE(mapper.update(connections)); + EXPECT_EQ(0u, mapper.size()); + EXPECT_EQ(3, mapper.end() - mapper.begin()); + } + // remap 7 connections to nothing + for (const boost::uuids::uuid& connection : boost::adaptors::slice(in_connections, 0, 7)) + EXPECT_TRUE(mapper.get_stem(connection).is_nil()); + + // select 3 of 30 connections, only 7 should be remapped to new indexes (but all to new uuids) + connections.resize(30); + std::generate(connections.begin(), connections.end(), random_uuid); + EXPECT_TRUE(mapper.update(connections)); + { + std::map<boost::uuids::uuid, std::size_t> used; + for (const boost::uuids::uuid& connection : in_connections) + { + const boost::uuids::uuid& out = mapper.get_stem(connection); + EXPECT_FALSE(out.is_nil()); + used[out]++; + } + + EXPECT_EQ(3u, used.size()); + for (const std::pair<boost::uuids::uuid, std::size_t>& entry : used) + EXPECT_EQ(3u, entry.second); + } +} |