diff --git a/src/Makefile.seedertest.include b/src/Makefile.seedertest.include --- a/src/Makefile.seedertest.include +++ b/src/Makefile.seedertest.include @@ -12,7 +12,10 @@ 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) diff --git a/src/seeder/bitcoin.h b/src/seeder/bitcoin.h --- a/src/seeder/bitcoin.h +++ b/src/seeder/bitcoin.h @@ -48,10 +48,11 @@ 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); diff --git a/src/seeder/test/CMakeLists.txt b/src/seeder/test/CMakeLists.txt --- a/src/seeder/test/CMakeLists.txt +++ b/src/seeder/test/CMakeLists.txt @@ -14,5 +14,7 @@ ) 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 --- a/src/seeder/test/seeder_tests.cpp +++ b/src/seeder/test/seeder_tests.cpp @@ -4,12 +4,146 @@ #define BOOST_TEST_MODULE Bitcoin Seeder Test Suite +#include +#include +#include +#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) -BOOST_AUTO_TEST_CASE(test_stub) { - BOOST_CHECK_EQUAL(true, true); +static const unsigned short SERVICE_PORT = 18444; +static const uint32_t VERACK_PAYLOAD = 0; +// After the 1000th addr, the seeder will only add one more address from an addr +// message. +static const int VADDR_SOFT_CAP = 1000; + +static const CService +CreateDummyServiceAndAddress(std::vector &vAddr) { + CNetAddr ip; + ip.SetInternal("foo.com"); + const CService service(ip, SERVICE_PORT); + CAddress addr(service, ServiceFlags()); + vAddr.clear(); + vAddr.push_back(addr); + return service; +} + +class TestCSeederNode : public CSeederNode { +public: + TestCSeederNode(const CService &service, std::vector *vAddrIn) + : CSeederNode(service, vAddrIn) { + SelectParams(CBaseChainParams::REGTEST); + } + + bool TestProcessMessage(const std::string &strCommand, + CDataStream message) { + return CSeederNode::ProcessMessage(strCommand, message); + } +}; + +static CDataStream +CreateVersionMessage(int64_t now, CAddress addrTo, CAddress addrFrom, + int32_t start_height, uint64_t nonce = 0, + uint16_t user_agent = 0, + uint32_t nVersion = INIT_PROTO_VERSION) { + CDataStream payload(SER_NETWORK, 0); + payload.SetVersion(nVersion); + ServiceFlags service = ServiceFlags(NODE_NETWORK); + payload << nVersion << uint64_t(service) << now << addrTo << addrFrom + << nonce << user_agent << start_height; + return payload; +} + +// Verack message consists of only the header with NetMsgType::VERACK as the +// command string. +static CDataStream CreateVerackMessage(uint32_t nVersion = INIT_PROTO_VERSION) { + CDataStream payload(SER_NETWORK, 0); + payload.SetVersion(nVersion); + payload << VERACK_PAYLOAD; + 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; +} + +BOOST_AUTO_TEST_CASE(seeder_node_version_test) { + std::vector vAddr; + const CService service = CreateDummyServiceAndAddress(vAddr); + TestCSeederNode testNode(service, &vAddr); + + CService serviceFrom; + CAddress addrFrom(serviceFrom, + ServiceFlags(NODE_NETWORK | NODE_BITCOIN_CASH)); + CDataStream versionMessage = CreateVersionMessage( + time(nullptr), vAddr[0], addrFrom, GetRequireHeight()); + + bool ret = testNode.TestProcessMessage(NetMsgType::VERSION, versionMessage); + BOOST_CHECK_EQUAL(ret, false); +} + +BOOST_AUTO_TEST_CASE(seeder_node_verack_test) { + std::vector vAddr; + const CService service = CreateDummyServiceAndAddress(vAddr); + TestCSeederNode testNode(service, &vAddr); + + CDataStream verackMessage = CreateVerackMessage(); + + bool ret = testNode.TestProcessMessage(NetMsgType::VERACK, verackMessage); + BOOST_CHECK_EQUAL(ret, false); +} + +BOOST_AUTO_TEST_CASE(seeder_node_addr_test_happy_path) { + std::vector vAddr; + const CService service = CreateDummyServiceAndAddress(vAddr); + TestCSeederNode testNode(service, &vAddr); + + CDataStream addrMessage = CreateAddrMessage(vAddr); + + bool ret = testNode.TestProcessMessage(NetMsgType::ADDR, addrMessage); + BOOST_CHECK_EQUAL(ret, false); + BOOST_CHECK_EQUAL(2, vAddr.size()); +} + +BOOST_AUTO_TEST_CASE(seeder_node_addr_test_soft_cap) { + std::vector vAddr; + const CService service = CreateDummyServiceAndAddress(vAddr); + TestCSeederNode testNode(service, &vAddr); + + // vAddr starts with 1 entry. Only need to add VADDR_SOFT_CAP - 1 + std::vector sendAddrs(VADDR_SOFT_CAP - 1, vAddr[0]); + CDataStream addrMessage = CreateAddrMessage(sendAddrs); + + // Maximum number of addrs is VADDR_SOFT_CAP. All addrs are added until the + // VADDR_SOFT_CAPth. + BOOST_CHECK_EQUAL(1, vAddr.size()); + bool ret = testNode.TestProcessMessage(NetMsgType::ADDR, addrMessage); + BOOST_CHECK_EQUAL(ret, false); + BOOST_CHECK_EQUAL(VADDR_SOFT_CAP, vAddr.size()); + + // After the VADDR_SOFT_CAPth, only one is added and the rest are ignored + ret = testNode.TestProcessMessage(NetMsgType::ADDR, addrMessage); + BOOST_CHECK_EQUAL(ret, true); + BOOST_CHECK_EQUAL(VADDR_SOFT_CAP + 1, vAddr.size()); } BOOST_AUTO_TEST_SUITE_END()