Bitcoin ABC 0.30.5
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>
7
8#include <string>
9#include <vector>
10
11#include <boost/test/unit_test.hpp>
12
13BOOST_AUTO_TEST_SUITE(write_name_tests)
14
15static 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
46static 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
80static void CheckWriteName(const std::string &qname, const int &offset = 12) {
82 CheckWriteNameWithOffset(qname, offset);
83}
84
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
95BOOST_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
105BOOST_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
115BOOST_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
134BOOST_AUTO_TEST_SUITE_END()
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:259
#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)