Changeset View
Changeset View
Standalone View
Standalone View
src/seeder/test/seeder_tests.cpp
- This file was added.
// Copyright (c) 2016 The Bitcoin Core developers | |||||
// Distributed under the MIT software license, see the accompanying | |||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | |||||
#include <seeder/dns.h> | |||||
#include <test/test_bitcoin.h> | |||||
#include <boost/test/unit_test.hpp> | |||||
#include <array> | |||||
#include <iostream> | |||||
#include <sstream> | |||||
#include <string> | |||||
BOOST_FIXTURE_TEST_SUITE(seeder_tests, BasicTestingSetup) | |||||
const int BUFFER_LENGTH = 512; | |||||
const int QNAME_BUFFER_LENGTH = 256; | |||||
const int SIZE_OF_DNS_MESSAGE_HEADER = 12; | |||||
const int SIZE_OF_QTYPE = 2; | |||||
const int SIZE_OF_QCLASS = 2; | |||||
// Builds dummy DNS query message | |||||
std::array<uint8_t, BUFFER_LENGTH> CreateDNSMessage(const std::string &qname) { | |||||
std::stringstream querryhex; | |||||
querryhex.clear(); | |||||
querryhex << std::hex << std::setfill('0'); | |||||
// ID | |||||
querryhex << std::setw(2) << static_cast<uint8_t>(0); | |||||
jasonbcox: Why does this need a static_cast? Won't `uint8_t(0)` suffice? | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsIgnore this. I missed that this was a typedef. jasonbcox: Ignore this. I missed that this was a typedef. | |||||
// QR to RD | |||||
querryhex << std::setw(1) << static_cast<uint8_t>(128); | |||||
// RA to RCODE | |||||
querryhex << std::setw(1) << static_cast<uint8_t>(0); | |||||
// QDCOUNT | |||||
querryhex << std::setw(2) << static_cast<uint8_t>(1); | |||||
// ANCOUNT | |||||
querryhex << std::setw(2) << static_cast<uint8_t>(0); | |||||
// NSCOUNT | |||||
querryhex << std::setw(2) << static_cast<uint8_t>(0); | |||||
// ARCOUNT | |||||
querryhex << std::setw(2) << static_cast<uint8_t>(0); | |||||
size_t i = 0; | |||||
size_t lastperiod = 0; | |||||
while (i < qname.size()) { | |||||
if (qname[i] == '.') { | |||||
querryhex << std::setw(1) << static_cast<uint8_t>(i - lastperiod); | |||||
while (lastperiod < i) { | |||||
querryhex << std::setw(1) | |||||
<< static_cast<uint8_t>(qname[lastperiod]); | |||||
lastperiod++; | |||||
} | |||||
lastperiod = i + 1; | |||||
} | |||||
i++; | |||||
} | |||||
querryhex << std::setw(1) << static_cast<uint8_t>(i - lastperiod); | |||||
while (lastperiod < i) { | |||||
querryhex << std::setw(1) << static_cast<uint8_t>(qname[lastperiod]); | |||||
lastperiod++; | |||||
} | |||||
// End of name field | |||||
querryhex << std::setw(1) << static_cast<uint8_t>(0); | |||||
// QTYPE = A query | |||||
querryhex << std::setw(2) << static_cast<uint8_t>(1); | |||||
// QCLASS = IN | |||||
querryhex << std::setw(2) << static_cast<uint8_t>(1); | |||||
std::array<uint8_t, BUFFER_LENGTH> messageBuffer; | |||||
messageBuffer.fill(0); | |||||
querryhex >> std::hex >> messageBuffer.data(); | |||||
return messageBuffer; | |||||
} | |||||
BOOST_AUTO_TEST_CASE(parse_name_simple) { | |||||
const std::string messageQName = "www.mydomain.com"; | |||||
std::array<uint8_t, BUFFER_LENGTH> inbuf; | |||||
inbuf.fill(0); | |||||
inbuf = CreateDNSMessage(messageQName); | |||||
std::array<char, QNAME_BUFFER_LENGTH> qname; | |||||
qname.fill(0); | |||||
ssize_t insize = QNAME_BUFFER_LENGTH; | |||||
const uint8_t *inpos = inbuf.data() + SIZE_OF_DNS_MESSAGE_HEADER; | |||||
// +1 for the last octet ending the field name | |||||
const uint8_t *inend = inbuf.data() + SIZE_OF_DNS_MESSAGE_HEADER + | |||||
messageQName.size() + 1 + SIZE_OF_QTYPE + | |||||
SIZE_OF_QCLASS; | |||||
int ret = parse_name(&inpos, inend, inbuf.data(), qname.data(), insize); | |||||
BOOST_CHECK_EQUAL(ret, 0); | |||||
BOOST_CHECK_EQUAL(qname.data(), messageQName); | |||||
// Test for insufficient output buffer size | |||||
qname.fill(0); | |||||
inpos = inbuf.data() + SIZE_OF_DNS_MESSAGE_HEADER; | |||||
ret = parse_name(&inpos, inend, inbuf.data(), qname.data(), | |||||
messageQName.size()); | |||||
BOOST_CHECK_EQUAL(ret, -2); | |||||
BOOST_CHECK_EQUAL(qname.data(), | |||||
messageQName.substr(0, messageQName.size() - 1)); | |||||
// Test for premature end of input buffer | |||||
qname.fill(0); | |||||
inpos = inbuf.data() + SIZE_OF_DNS_MESSAGE_HEADER; | |||||
ret = parse_name(&inpos, inpos + 2, inbuf.data(), qname.data(), insize); | |||||
BOOST_CHECK_EQUAL(ret, -1); | |||||
BOOST_CHECK_EQUAL(qname.data(), messageQName.substr(0, 1)); | |||||
// Test for when name field is too long | |||||
std::string longMessageQName = "www."; | |||||
for (size_t i = 0; i < 65; i++) { | |||||
longMessageQName += 'a'; | |||||
} | |||||
longMessageQName += ".com"; | |||||
qname.fill(0); | |||||
std::array<uint8_t, BUFFER_LENGTH> longInbuf; | |||||
longInbuf.fill(0); | |||||
longInbuf = CreateDNSMessage(longMessageQName); | |||||
const uint8_t *longInpos = longInbuf.data() + SIZE_OF_DNS_MESSAGE_HEADER; | |||||
const uint8_t *longInend = longInbuf.data() + SIZE_OF_DNS_MESSAGE_HEADER + | |||||
longMessageQName.size() + 1 + SIZE_OF_QTYPE + | |||||
SIZE_OF_QCLASS; | |||||
ret = parse_name(&longInpos, longInend, longInbuf.data(), qname.data(), | |||||
insize); | |||||
BOOST_CHECK_EQUAL(ret, -1); | |||||
} | |||||
BOOST_AUTO_TEST_SUITE_END() |
Why does this need a static_cast? Won't uint8_t(0) suffice?