diff --git a/src/Makefile.seedertest.include b/src/Makefile.seedertest.include index d3b96d2e8..affef7c9e 100644 --- a/src/Makefile.seedertest.include +++ b/src/Makefile.seedertest.include @@ -1,25 +1,28 @@ # Copyright (c) 2019 The Bitcoin developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. bin_PROGRAMS += seeder/test/test_bitcoin-seeder TESTS += seeder/test/test_bitcoin-seeder seeder_test_test_bitcoin_seeder_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_SEEDER_INCLUDES) \ $(SEEDER_INCLUDES) $(SEEDER_TEST_INCLUDES) $(TESTDEFS) seeder_test_test_bitcoin_seeder_SOURCES = \ seeder/test/seeder_tests.cpp seeder_test_test_bitcoin_seeder_LDADD = $(LIBBITCOIN_SEEDER) -seeder_test_test_bitcoin_seeder_LDADD += $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) + +seeder_test_test_bitcoin_seeder_LDADD += $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UTIL) \ + $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(CRYPTO_LIBS) + seeder_test_test_bitcoin_seeder_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) seeder_test_test_bitcoin_seeder_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_bitcoin_seeder : seeder/test/test_bitcoin-seeder$(EXEEXT) test_bitcoin_seeder_check : seeder/test/test_bitcoin-seeder$(EXEEXT) FORCE $(MAKE) check-TESTS TESTS=$^ test_bitcoin_seeder_clean: FORCE rm -f $(seeder_test_test_bitcoin_seeder_OBJECTS) diff --git a/src/seeder/bitcoin.h b/src/seeder/bitcoin.h index 51e8208b5..0ee0ab812 100644 --- a/src/seeder/bitcoin.h +++ b/src/seeder/bitcoin.h @@ -1,72 +1,73 @@ // Copyright (c) 2017-2019 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_SEEDER_BITCOIN_H #define BITCOIN_SEEDER_BITCOIN_H #include #include #include #include #include static inline unsigned short GetDefaultPort() { return Params().GetDefaultPort(); } // The network magic to use. extern CMessageHeader::MessageMagic netMagic; class CSeederNode { private: SOCKET sock; CDataStream vSend; CDataStream vRecv; uint32_t nHeaderStart; uint32_t nMessageStart; int nVersion; std::string strSubVer; int nStartingHeight; std::vector *vAddr; int ban; int64_t doneAfter; CAddress you; int GetTimeout() { return you.IsTor() ? 120 : 30; } void BeginMessage(const char *pszCommand); void AbortMessage(); void EndMessage(); void Send(); void PushVersion(); void GotVersion(); - bool ProcessMessage(std::string strCommand, CDataStream &recv); - bool ProcessMessages(); +protected: + bool ProcessMessage(std::string strCommand, CDataStream &recv); + public: CSeederNode(const CService &ip, std::vector *vAddrIn); bool Run(); int GetBan() { return ban; } int GetClientVersion() { return nVersion; } std::string GetClientSubVersion() { return strSubVer; } int GetStartingHeight() { return nStartingHeight; } }; bool TestNode(const CService &cip, int &ban, int &client, std::string &clientSV, int &blocks, std::vector *vAddr); #endif // BITCOIN_SEEDER_BITCOIN_H diff --git a/src/seeder/test/CMakeLists.txt b/src/seeder/test/CMakeLists.txt index 84cfcabbe..f36a7f6a9 100644 --- a/src/seeder/test/CMakeLists.txt +++ b/src/seeder/test/CMakeLists.txt @@ -1,18 +1,20 @@ # Copyright (c) 2019 The Bitcoin developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. project(bitcoin-seeder-test) include(TestSuite) create_test_suite(bitcoin-seeder) add_dependencies(check check-bitcoin-seeder) add_boost_unit_tests_to_suite(bitcoin-seeder test_bitcoin-seeder TESTS seeder_tests.cpp ) target_link_libraries(test_bitcoin-seeder + common + bitcoinconsensus seeder-netprocessing ) diff --git a/src/seeder/test/seeder_tests.cpp b/src/seeder/test/seeder_tests.cpp index 9b279e717..ea34ae7a6 100644 --- a/src/seeder/test/seeder_tests.cpp +++ b/src/seeder/test/seeder_tests.cpp @@ -1,15 +1,137 @@ // Copyright (c) 2019 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #define BOOST_TEST_MODULE Bitcoin Seeder Test Suite +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +const std::function G_TRANSLATION_FUN = nullptr; + #include -BOOST_AUTO_TEST_SUITE(seeder_tests) +static const unsigned short SERVICE_PORT = 18444; +static const int SEEDER_INIT_VERSION = 0; +// After the 1000th addr, the seeder will only add one more address per addr +// message. +static const int ADDR_SOFT_CAP = 1000; + +enum PeerMessagingState : bool { + Finished = true, + AwaitingMessages = false, +}; + +static CDataStream +CreateVersionMessage(int64_t now, CAddress addrTo, CAddress addrFrom, + int32_t start_height, uint32_t nVersion, + uint64_t nonce = 0, + std::string user_agent = "/bitcoin-cash-seeder:0.15/") { + CDataStream payload(SER_NETWORK, 0); + payload.SetVersion(nVersion); + ServiceFlags serviceflags = ServiceFlags(NODE_NETWORK); + payload << nVersion << uint64_t(serviceflags) << now << addrTo << addrFrom + << nonce << user_agent << start_height; + return payload; +} + +static CDataStream CreateAddrMessage(std::vector sendAddrs, + uint32_t nVersion = INIT_PROTO_VERSION) { + CDataStream payload(SER_NETWORK, 0); + payload.SetVersion(nVersion); + payload << sendAddrs; + return payload; +} + +class TestCSeederNode : public CSeederNode { +public: + TestCSeederNode(const CService &service, std::vector *vAddrIn) + : CSeederNode(service, vAddrIn) { + SelectParams(CBaseChainParams::REGTEST); + } + + void TestProcessMessage(const std::string &strCommand, CDataStream &message, + PeerMessagingState state) { + bool ret = CSeederNode::ProcessMessage(strCommand, message); + BOOST_CHECK_EQUAL(ret, bool(state)); + } +}; + +struct SeederTestingSetup { + SeederTestingSetup() { + CNetAddr ip; + ip.SetInternal("bitcoin.test"); + CService service = {ip, SERVICE_PORT}; + vAddr.emplace_back(service, ServiceFlags()); + testNode = std::make_unique(service, &vAddr); + } + + std::vector vAddr; + std::unique_ptr testNode; +}; + +BOOST_FIXTURE_TEST_SUITE(seeder_tests, SeederTestingSetup) + +BOOST_AUTO_TEST_CASE(seeder_node_version_test) { + CService serviceFrom; + CAddress addrFrom(serviceFrom, + ServiceFlags(NODE_NETWORK | NODE_BITCOIN_CASH)); + + CDataStream versionMessage = + CreateVersionMessage(time(nullptr), vAddr[0], addrFrom, + GetRequireHeight(), INIT_PROTO_VERSION); + + // Verify the version is set as the initial value + BOOST_CHECK_EQUAL(testNode->CSeederNode::GetClientVersion(), + SEEDER_INIT_VERSION); + testNode->TestProcessMessage(NetMsgType::VERSION, versionMessage, + PeerMessagingState::AwaitingMessages); + // Verify the version has been updated + BOOST_CHECK_EQUAL(testNode->CSeederNode::GetClientVersion(), + versionMessage.GetVersion()); +} + +BOOST_AUTO_TEST_CASE(seeder_node_addr_test) { + // vAddrs starts with 1 entry. + std::vector sendAddrs(ADDR_SOFT_CAP - 1, vAddr[0]); + + // Happy path + // addrs are added normally to vAddr until ADDR_SOFT_CAP is reached. + // Add addrs up to the soft cap. + CDataStream addrMessage = CreateAddrMessage(sendAddrs); + BOOST_CHECK_EQUAL(1, vAddr.size()); + testNode->TestProcessMessage(NetMsgType::ADDR, addrMessage, + PeerMessagingState::AwaitingMessages); + BOOST_CHECK_EQUAL(ADDR_SOFT_CAP, vAddr.size()); + + // ADDR_SOFT_CAP is exceeded + sendAddrs.resize(1); + addrMessage = CreateAddrMessage(sendAddrs); + testNode->TestProcessMessage(NetMsgType::ADDR, addrMessage, + PeerMessagingState::Finished); + BOOST_CHECK_EQUAL(ADDR_SOFT_CAP + 1, vAddr.size()); -BOOST_AUTO_TEST_CASE(test_stub) { - BOOST_CHECK_EQUAL(true, true); + // Test the seeder's behavior after ADDR_SOFT_CAP addrs + // Only one addr per ADDR message will be added, the rest are ignored + size_t expectedSize = vAddr.size() + 1; + for (size_t i = 1; i < 10; i++) { + sendAddrs.resize(i, sendAddrs[0]); + addrMessage = CreateAddrMessage(sendAddrs); + testNode->TestProcessMessage(NetMsgType::ADDR, addrMessage, + PeerMessagingState::Finished); + BOOST_CHECK_EQUAL(expectedSize, vAddr.size()); + ++expectedSize; + } } BOOST_AUTO_TEST_SUITE_END()