Bitcoin ABC  0.29.2
P2P Digital Currency
write_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 
8 #include <string>
9 #include <vector>
10 
11 #include <boost/test/unit_test.hpp>
12 
13 BOOST_AUTO_TEST_SUITE(write_name_tests)
14 
15 static void CheckWriteNameNoOffset(const std::string &qname) {
16  size_t writeBufferSize = 0;
17  // +1 for the length of the first label and +1 for the END_OF_NAME_FIELD
18  // characters
19  while (writeBufferSize < qname.size() + 2) {
20  std::vector<uint8_t> writtenName(writeBufferSize, 0);
21  uint8_t *writtenNameBegin = writtenName.data();
22  int ret =
23  write_name(&writtenNameBegin, writtenNameBegin + writeBufferSize,
24  qname.c_str(), -1);
25  BOOST_CHECK_EQUAL(ret, -2);
26  writeBufferSize++;
27  }
28 
29  // Happy path
30  std::vector<uint8_t> expectedName = CreateDNSQuestionNameField(qname);
31  while (writeBufferSize <= MAX_QUERY_NAME_LENGTH) {
32  std::vector<uint8_t> writtenName(writeBufferSize, 0);
33  uint8_t *writtenNameBegin = writtenName.data();
34  int ret =
35  write_name(&writtenNameBegin, writtenNameBegin + writeBufferSize,
36  qname.c_str(), -1);
37  BOOST_CHECK_EQUAL(ret, 0);
38  BOOST_CHECK(writtenName.size() >= expectedName.size());
39  for (size_t i = 0; i < expectedName.size(); i++) {
40  BOOST_CHECK_EQUAL(writtenName[i], expectedName[i]);
41  }
42  writeBufferSize++;
43  }
44 }
45 
46 static void CheckWriteNameWithOffset(const std::string &qname,
47  const int &offset = 12) {
48  size_t writeBufferSize = 0;
49  // +1 for the length of the first label and +2 for the offset
50  // characters
51  while (writeBufferSize < qname.size() + 3) {
52  std::vector<uint8_t> writtenName(writeBufferSize, 0);
53  uint8_t *writtenNameBegin = writtenName.data();
54  int ret =
55  write_name(&writtenNameBegin, writtenNameBegin + writeBufferSize,
56  qname.c_str(), offset);
57  BOOST_CHECK_EQUAL(ret, -2);
58  writeBufferSize++;
59  }
60 
61  // Happy path
62  std::vector<uint8_t> expectedName = CreateDNSQuestionNameField(qname);
63  expectedName[expectedName.size() - 1] = (offset >> 8) | 0xC0;
64  expectedName.push_back(uint8_t(offset));
65  while (writeBufferSize <= MAX_QUERY_NAME_LENGTH) {
66  std::vector<uint8_t> writtenName(writeBufferSize, 0);
67  uint8_t *writtenNameBegin = writtenName.data();
68  int ret =
69  write_name(&writtenNameBegin, writtenNameBegin + writeBufferSize,
70  qname.c_str(), offset);
71  BOOST_CHECK_EQUAL(ret, 0);
72  BOOST_CHECK(writtenName.size() >= expectedName.size());
73  for (size_t i = 0; i < expectedName.size(); i++) {
74  BOOST_CHECK_EQUAL(writtenName[i], expectedName[i]);
75  }
76  writeBufferSize++;
77  }
78 }
79 
80 static void CheckWriteName(const std::string &qname, const int &offset = 12) {
82  CheckWriteNameWithOffset(qname, offset);
83 }
84 
85 static void CheckWriteNameError(
86  const std::string &qname, const int &expectedError, const int &offset = -1,
87  const size_t &writeBufferSize = MAX_QUERY_NAME_BUFFER_LENGTH) {
88  std::vector<uint8_t> writtenName(writeBufferSize, 0);
89  uint8_t *writtenNameBegin = writtenName.data();
90  int ret = write_name(&writtenNameBegin, writtenNameBegin + writeBufferSize,
91  qname.c_str(), -1);
92  BOOST_CHECK_EQUAL(ret, expectedError);
93 }
94 
95 BOOST_AUTO_TEST_CASE(write_name_simple_tests) {
96  CheckWriteName("www.domain.com");
97  CheckWriteName("domain.com");
98  CheckWriteName("sub1.sub2.domain.co.uk");
99  // Shortest valid domain name is 1 char followed by the extension
100  CheckWriteName("a.co");
101  // Domain name with valid non-alphanumeric character
102  CheckWriteName("my-domain.com");
103 }
104 
105 BOOST_AUTO_TEST_CASE(write_name_label_tests) {
106  // Check behavior for name with maximum length label
107  const std::string maxLengthLabel(MAX_LABEL_LENGTH, 'a');
108  CheckWriteName("www." + maxLengthLabel + ".com");
109 
110  // Check that an oversized label causes an error
111  CheckWriteNameError("www." + maxLengthLabel + "a.com", -1);
112  CheckWriteNameError("www." + maxLengthLabel + "a.com", -1, 12);
113 }
114 
115 BOOST_AUTO_TEST_CASE(write_name_qname_length_tests) {
116  const std::string maxLengthLabel(MAX_LABEL_LENGTH, 'a');
117 
118  // Check behavior for a name that is the maximum length
119  std::string maxLengthQName = maxLengthLabel + '.' + maxLengthLabel + '.' +
120  maxLengthLabel + '.' + maxLengthLabel;
121  BOOST_CHECK_EQUAL(maxLengthQName.size(), MAX_QUERY_NAME_LENGTH);
122  CheckWriteName(maxLengthQName);
123 
124  // Check that a query name that is too long causes an error
125  std::string oversizedQName = maxLengthQName;
126  // Split the last label into two while adding an extra character to make
127  // sure the function does not error because of an oversized label
128  oversizedQName.insert(oversizedQName.end() - 3, '.');
129  // Allocates an extra large buffer to guarantee an error is not caused by
130  // the buffer size
131  CheckWriteNameError(oversizedQName, -2, 2 * oversizedQName.size());
132 }
133 
int write_name(uint8_t **outpos, const uint8_t *outend, const char *name, int offset)
Definition: dns.cpp:132
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
static void CheckWriteName(const std::string &qname, const int &offset=12)
BOOST_AUTO_TEST_CASE(write_name_simple_tests)
static void CheckWriteNameNoOffset(const std::string &qname)
static void CheckWriteNameWithOffset(const std::string &qname, const int &offset=12)
static void CheckWriteNameError(const std::string &qname, const int &expectedError, const int &offset=-1, const size_t &writeBufferSize=MAX_QUERY_NAME_BUFFER_LENGTH)