Bitcoin ABC  0.26.3
P2P Digital Currency
parse_name_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019 The Bitcoin developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <seeder/dns.h>
6 #include <seeder/test/dns_util.h>
7 #include <seeder/test/util.h>
8 
9 #include <ostream>
10 #include <string>
11 #include <vector>
12 
13 #include <boost/test/unit_test.hpp>
14 
15 std::ostream &operator<<(std::ostream &os, const ParseNameStatus &status) {
16  os << to_integral(status);
17  return os;
18 }
19 
20 BOOST_AUTO_TEST_SUITE(parse_name_tests)
21 
22 static void CheckParseName(const std::string &queryName) {
23  std::vector<uint8_t> nameField = CreateDNSQuestionNameField(queryName);
24 
25  // Test when name field is too short to reach null-terminator
26  for (size_t nameFieldEndIndex = 0; nameFieldEndIndex < nameField.size();
27  nameFieldEndIndex++) {
28  std::vector<char> parsedQueryName(MAX_QUERY_NAME_BUFFER_LENGTH, 0);
29  const uint8_t *nameFieldBegin = nameField.data();
31  &nameFieldBegin, nameFieldBegin + nameFieldEndIndex,
32  nameField.data(), parsedQueryName.data(), parsedQueryName.size());
33 
35  }
36 
37  // Test when the buffer size is too small
38  size_t outputBufferSize = 0;
39  while (outputBufferSize <= queryName.size()) {
40  std::vector<char> parsedQueryName(outputBufferSize, 0);
41  const uint8_t *nameFieldBegin = nameField.data();
43  &nameFieldBegin, nameFieldBegin + nameField.size(),
44  nameField.data(), parsedQueryName.data(), parsedQueryName.size());
46  outputBufferSize++;
47  }
48 
49  // Happy path
50  while (outputBufferSize <= MAX_QUERY_NAME_BUFFER_LENGTH) {
51  std::vector<char> parsedQueryName(outputBufferSize, 0);
52  const uint8_t *nameFieldBegin = nameField.data();
54  &nameFieldBegin, nameFieldBegin + nameField.size(),
55  nameField.data(), parsedQueryName.data(), parsedQueryName.size());
57  BOOST_CHECK_EQUAL(parsedQueryName.data(), queryName);
58  outputBufferSize++;
59  }
60 }
61 
62 static void CheckParseNameError(
63  const std::string &queryName, const ParseNameStatus expectedError,
64  const size_t &outputBufferSize = MAX_QUERY_NAME_BUFFER_LENGTH) {
65  std::vector<uint8_t> nameField = CreateDNSQuestionNameField(queryName);
66 
67  std::vector<char> parsedQueryName(outputBufferSize, 0);
68  const uint8_t *nameFieldBegin = nameField.data();
70  &nameFieldBegin, nameFieldBegin + nameField.size(), nameField.data(),
71  parsedQueryName.data(), parsedQueryName.size());
72 
73  BOOST_CHECK_EQUAL(ret, expectedError);
74 }
75 
76 BOOST_AUTO_TEST_CASE(parse_name_simple_tests) {
77  CheckParseName("www.domain.com");
78  CheckParseName("domain.com");
79  CheckParseName("sub1.sub2.domain.co.uk");
80  // Shortest valid domain name is 1 char followed by the extension
81  CheckParseName("a.co");
82  // Domain name with valid non-alphanumeric character
83  CheckParseName("my-domain.com");
84 }
85 
86 BOOST_AUTO_TEST_CASE(parse_name_label_tests) {
87  // Check behavior for name with maximum length label
88  const std::string maxLengthLabel(MAX_LABEL_LENGTH, 'a');
89  CheckParseName("www." + maxLengthLabel + ".com");
90 
91  // Check that an oversized label causes an error
92  CheckParseNameError("www." + maxLengthLabel + "a.com",
94 }
95 
96 BOOST_AUTO_TEST_CASE(parse_name_qname_length_tests) {
97  const std::string maxLengthLabel(MAX_LABEL_LENGTH, 'a');
98 
99  // Check behavior for a name that is the maximum length
100  std::string maxLengthQName = maxLengthLabel + '.' + maxLengthLabel + '.' +
101  maxLengthLabel + '.' + maxLengthLabel;
102  BOOST_CHECK_EQUAL(maxLengthQName.size(), MAX_QUERY_NAME_LENGTH);
103  CheckParseName(maxLengthQName);
104 
105  // Check that a query name that is too long causes an error
106  std::string overSizedQName = maxLengthQName;
107  // Split the last label into two while adding an extra character to make
108  // sure the function does not error because of an oversized label
109  overSizedQName.insert(overSizedQName.end() - 3, '.');
110  // Allocates an extra large buffer to guarantee an error is not caused by
111  // the buffer size
113  2 * overSizedQName.size());
114 }
115 
ParseNameStatus parse_name(const uint8_t **inpos, const uint8_t *inend, const uint8_t *inbuf, char *buf, size_t bufsize)
Definition: dns.cpp:66
ParseNameStatus
Definition: dns.h:38
constexpr int MAX_LABEL_LENGTH
Definition: dns.h:11
constexpr int MAX_QUERY_NAME_LENGTH
Definition: dns.h:12
constexpr int MAX_QUERY_NAME_BUFFER_LENGTH
Definition: dns.h:14
static std::vector< uint8_t > CreateDNSQuestionNameField(const std::string &queryName)
Definition: dns_util.h:15
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:257
#define BOOST_AUTO_TEST_SUITE_END()
Definition: object.cpp:16
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
std::ostream & operator<<(std::ostream &os, const ParseNameStatus &status)
static void CheckParseName(const std::string &queryName)
BOOST_AUTO_TEST_CASE(parse_name_simple_tests)
static void CheckParseNameError(const std::string &queryName, const ParseNameStatus expectedError, const size_t &outputBufferSize=MAX_QUERY_NAME_BUFFER_LENGTH)
constexpr std::underlying_type< E >::type to_integral(E e)
Definition: util.h:11