Changeset View
Changeset View
Standalone View
Standalone View
src/seeder/test/seeder_tests.cpp
// Copyright (c) 2019 The Bitcoin developers | // Copyright (c) 2019 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#define BOOST_TEST_MODULE Bitcoin Seeder Test Suite | #define BOOST_TEST_MODULE Bitcoin Seeder Test Suite | ||||
#include <seeder/dns.h> | |||||
#include <array> | |||||
#include <string> | |||||
#include <vector> | |||||
#include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||
BOOST_AUTO_TEST_SUITE(seeder_tests) | BOOST_AUTO_TEST_SUITE(seeder_tests) | ||||
BOOST_AUTO_TEST_CASE(test_stub) { | static const int MAX_QUERY_NAME_LENGTH = 255; | ||||
BOOST_CHECK_EQUAL(true, true); | static const uint8_t END_OF_NAME_FIELD = 0; | ||||
static const size_t MAX_LABEL_LENGTH = 63; | |||||
// Builds the name field of the question section of a DNS query | |||||
static std::vector<uint8_t> | |||||
CreateDNSQuestionNameField(const std::string &queryName) { | |||||
std::vector<uint8_t> nameField; | |||||
size_t i = 0; | |||||
size_t labelIndex = 0; | |||||
while (i < queryName.size()) { | |||||
if (queryName[i] == '.') { | |||||
// Push the length of the label and then the label | |||||
nameField.push_back(i - labelIndex); | |||||
while (labelIndex < i) { | |||||
nameField.push_back(queryName[labelIndex]); | |||||
labelIndex++; | |||||
} | |||||
labelIndex = i + 1; | |||||
} | |||||
i++; | |||||
} | |||||
// Push the length of the label and then the label | |||||
nameField.push_back(i - labelIndex); | |||||
while (labelIndex < i) { | |||||
nameField.push_back(queryName[labelIndex]); | |||||
labelIndex++; | |||||
} | |||||
nameField.push_back(END_OF_NAME_FIELD); | |||||
return nameField; | |||||
} | |||||
static void CheckParseName(const std::string queryName) { | |||||
std::vector<uint8_t> nameField = CreateDNSQuestionNameField(queryName); | |||||
// Input buffer tests | |||||
// parse_name() does not support input strings of length 0 | |||||
for (size_t nameFieldEndIndex = 1; | |||||
nameFieldEndIndex < MAX_QUERY_NAME_LENGTH; nameFieldEndIndex++) { | |||||
std::array<char, MAX_QUERY_NAME_LENGTH> parsedQueryName; | |||||
parsedQueryName.fill(0); | |||||
const uint8_t *nameFieldBegin = nameField.data(); | |||||
int ret = parse_name( | |||||
&nameFieldBegin, nameFieldBegin + nameFieldEndIndex, | |||||
nameField.data(), parsedQueryName.data(), parsedQueryName.size()); | |||||
if (nameFieldEndIndex < nameField.size()) { | |||||
BOOST_CHECK(ret != 0); | |||||
} else { | |||||
BOOST_CHECK(ret == 0); | |||||
BOOST_CHECK_EQUAL(parsedQueryName.data(), | |||||
queryName.substr(0, nameFieldEndIndex - 1)); | |||||
} | |||||
} | |||||
// Output buffer size test | |||||
std::array<char, MAX_QUERY_NAME_LENGTH> parsedQueryName; | |||||
parsedQueryName.fill(0); | |||||
const uint8_t *nameFieldBegin = nameField.data(); | |||||
int ret = | |||||
parse_name(&nameFieldBegin, nameFieldBegin + nameField.size(), | |||||
nameField.data(), parsedQueryName.data(), queryName.size()); | |||||
BOOST_CHECK(ret != 0); | |||||
} | |||||
BOOST_AUTO_TEST_CASE(parse_name_tests) { | |||||
CheckParseName("www.domain.com"); | |||||
CheckParseName("domain.com"); | |||||
// Shortest valid domain name is 1 char followed by the extension | |||||
CheckParseName("a.co"); | |||||
CheckParseName("sub1.sub2.domain.co.uk"); | |||||
CheckParseName("my-domain.com"); | |||||
// Check behavior for name with maximum length label | |||||
std::string maxLengthLabel; | |||||
for (size_t i = 0; i < MAX_LABEL_LENGTH; i++) { | |||||
maxLengthLabel += 'a'; | |||||
} | |||||
BOOST_CHECK_EQUAL(maxLengthLabel.size(), MAX_LABEL_LENGTH); | |||||
CheckParseName("www." + maxLengthLabel + ".com"); | |||||
// Check behavior for a name that is the maximum length | |||||
std::string maxLengthQName = maxLengthLabel + '.' + maxLengthLabel + '.' + | |||||
maxLengthLabel + '.' + maxLengthLabel; | |||||
BOOST_CHECK_EQUAL(maxLengthQName.size(), MAX_QUERY_NAME_LENGTH); | |||||
CheckParseName(maxLengthQName); | |||||
} | |||||
// Test for when a label in the name field is too long | |||||
BOOST_AUTO_TEST_CASE(parse_name_label_too_long) { | |||||
// Verify that MAX_LABEL_LENGTH + 1 fails | |||||
std::string maxLengthLabel; | |||||
for (size_t i = 0; i < MAX_LABEL_LENGTH; i++) { | |||||
maxLengthLabel += 'a'; | |||||
} | |||||
BOOST_CHECK_EQUAL(maxLengthLabel.size(), MAX_LABEL_LENGTH); | |||||
std::string queryName = "www." + maxLengthLabel + "a.com"; | |||||
std::vector<uint8_t> nameField = CreateDNSQuestionNameField(queryName); | |||||
std::array<char, MAX_QUERY_NAME_LENGTH> parsedQueryName; | |||||
parsedQueryName.fill(0); | |||||
const uint8_t *nameFieldBegin = nameField.data(); | |||||
int ret = parse_name(&nameFieldBegin, nameFieldBegin + nameField.size(), | |||||
nameField.data(), parsedQueryName.data(), | |||||
MAX_QUERY_NAME_LENGTH); | |||||
BOOST_CHECK_EQUAL(ret, -1); | |||||
} | } | ||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |