1 // Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7 #include <config.h>
8
9 #include <string>
10
11 #include <util/buffer.h>
12 #include <dns/exceptions.h>
13 #include <dns/messagerenderer.h>
14 #include <dns/rdata.h>
15 #include <dns/rdataclass.h>
16 #include <dns/rrclass.h>
17 #include <dns/rrtype.h>
18
19 #include <gtest/gtest.h>
20
21 #include <dns/tests/unittest_util.h>
22 #include <dns/tests/rdata_unittest.h>
23 #include <util/unittests/wiredata.h>
24
25 using namespace std;
26 using namespace isc::util;
27 using namespace isc::dns;
28 using namespace isc::dns::rdata;
29 using isc::UnitTestUtil;
30 using isc::util::unittests::matchWireData;
31
32 namespace {
33 class Rdata_MINFO_Test : public RdataTest {
34 protected:
Rdata_MINFO_Test()35 Rdata_MINFO_Test():
36 minfo_txt("rmailbox.example.com. emailbox.example.com."),
37 minfo_txt2("root.example.com. emailbox.example.com."),
38 too_long_label("01234567890123456789012345678901234567"
39 "89012345678901234567890123."),
40 rdata_minfo(minfo_txt),
41 rdata_minfo2(minfo_txt2)
42 {}
43
checkFromText_None(const string & rdata_str)44 void checkFromText_None(const string& rdata_str) {
45 checkFromText<generic::MINFO, isc::Exception, isc::Exception>(
46 rdata_str, rdata_minfo, false, false);
47 }
48
checkFromText_LexerError(const string & rdata_str)49 void checkFromText_LexerError(const string& rdata_str) {
50 checkFromText
51 <generic::MINFO, InvalidRdataText, MasterLexer::LexerError>(
52 rdata_str, rdata_minfo, true, true);
53 }
54
checkFromText_TooLongLabel(const string & rdata_str)55 void checkFromText_TooLongLabel(const string& rdata_str) {
56 checkFromText<generic::MINFO, TooLongLabel, TooLongLabel>(
57 rdata_str, rdata_minfo, true, true);
58 }
59
checkFromText_BadString(const string & rdata_str)60 void checkFromText_BadString(const string& rdata_str) {
61 checkFromText<generic::MINFO, InvalidRdataText, isc::Exception>(
62 rdata_str, rdata_minfo, true, false);
63 }
64
checkFromText_EmptyLabel(const string & rdata_str)65 void checkFromText_EmptyLabel(const string& rdata_str) {
66 checkFromText<generic::MINFO, EmptyLabel, EmptyLabel>(
67 rdata_str, rdata_minfo, true, true);
68 }
69
checkFromText_MissingOrigin(const string & rdata_str)70 void checkFromText_MissingOrigin(const string& rdata_str) {
71 checkFromText
72 <generic::MINFO, MissingNameOrigin, MissingNameOrigin>(
73 rdata_str, rdata_minfo, true, true);
74 }
75
checkFromText_Origin(const string & rdata_str,const Name * origin)76 void checkFromText_Origin(const string& rdata_str, const Name* origin) {
77 checkFromText<generic::MINFO, MissingNameOrigin, isc::Exception>(
78 rdata_str, rdata_minfo, true, false, origin);
79 }
80
81 const string minfo_txt;
82 const string minfo_txt2;
83 const string too_long_label;
84 const generic::MINFO rdata_minfo;
85 const generic::MINFO rdata_minfo2;
86 };
87
88
TEST_F(Rdata_MINFO_Test,createFromText)89 TEST_F(Rdata_MINFO_Test, createFromText) {
90 EXPECT_EQ(Name("rmailbox.example.com."), rdata_minfo.getRmailbox());
91 EXPECT_EQ(Name("emailbox.example.com."), rdata_minfo.getEmailbox());
92
93 EXPECT_EQ(Name("root.example.com."), rdata_minfo2.getRmailbox());
94 EXPECT_EQ(Name("emailbox.example.com."), rdata_minfo2.getEmailbox());
95
96 checkFromText_None(minfo_txt);
97
98 // origin defined for lexer constructor, but not string constructor
99 const Name origin("example.com");
100 checkFromText_Origin("rmailbox emailbox", &origin);
101
102 // lexer constructor accepts extra text, but string constructor doesn't
103 checkFromText_BadString("rmailbox.example.com. emailbox.example.com. "
104 "extra.example.com.");
105 }
106
TEST_F(Rdata_MINFO_Test,badText)107 TEST_F(Rdata_MINFO_Test, badText) {
108 // too long names
109 checkFromText_TooLongLabel("root.example.com." + too_long_label +
110 " emailbox.example.com.");
111 checkFromText_TooLongLabel("root.example.com. emailbox.example.com." +
112 too_long_label);
113
114 // invalid names
115 checkFromText_EmptyLabel("root..example.com. emailbox.example.com.");
116 checkFromText_EmptyLabel("root.example.com. emailbox..example.com.");
117
118 // missing name
119 checkFromText_LexerError("root.example.com.");
120
121 // missing origin
122 checkFromText_MissingOrigin("root.example.com emailbox.example.com.");
123 checkFromText_MissingOrigin("root.example.com. emailbox.example.com");
124 }
125
TEST_F(Rdata_MINFO_Test,createFromWire)126 TEST_F(Rdata_MINFO_Test, createFromWire) {
127 // uncompressed names
128 EXPECT_EQ(0, rdata_minfo.compare(
129 *rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
130 "rdata_minfo_fromWire1.wire")));
131 // compressed names
132 EXPECT_EQ(0, rdata_minfo.compare(
133 *rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
134 "rdata_minfo_fromWire2.wire", 15)));
135 // RDLENGTH is too short
136 EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
137 "rdata_minfo_fromWire3.wire"),
138 InvalidRdataLength);
139 // RDLENGTH is too long
140 EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
141 "rdata_minfo_fromWire4.wire"),
142 InvalidRdataLength);
143 // bogus rmailbox name, the error should be detected in the name
144 // constructor
145 EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
146 "rdata_minfo_fromWire5.wire"),
147 DNSMessageFORMERR);
148 // bogus emailbox name, the error should be detected in the name
149 // constructor
150 EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
151 "rdata_minfo_fromWire6.wire"),
152 DNSMessageFORMERR);
153 }
154
TEST_F(Rdata_MINFO_Test,assignment)155 TEST_F(Rdata_MINFO_Test, assignment) {
156 generic::MINFO copy((string(minfo_txt2)));
157 copy = rdata_minfo;
158 EXPECT_EQ(0, copy.compare(rdata_minfo));
159
160 // Check if the copied data is valid even after the original is deleted
161 generic::MINFO* copy2 = new generic::MINFO(rdata_minfo);
162 generic::MINFO copy3((string(minfo_txt2)));
163 copy3 = *copy2;
164 delete copy2;
165 EXPECT_EQ(0, copy3.compare(rdata_minfo));
166
167 // Self assignment
168 copy = *©
169 EXPECT_EQ(0, copy.compare(rdata_minfo));
170 }
171
TEST_F(Rdata_MINFO_Test,toWireBuffer)172 TEST_F(Rdata_MINFO_Test, toWireBuffer) {
173 rdata_minfo.toWire(obuffer);
174 vector<unsigned char> data;
175 UnitTestUtil::readWireData("rdata_minfo_toWireUncompressed1.wire", data);
176 matchWireData(&data[0], data.size(),
177 obuffer.getData(), obuffer.getLength());
178
179 obuffer.clear();
180 rdata_minfo2.toWire(obuffer);
181 vector<unsigned char> data2;
182 UnitTestUtil::readWireData("rdata_minfo_toWireUncompressed2.wire", data2);
183 matchWireData(&data2[0], data2.size(),
184 obuffer.getData(), obuffer.getLength());
185 }
186
TEST_F(Rdata_MINFO_Test,toWireRenderer)187 TEST_F(Rdata_MINFO_Test, toWireRenderer) {
188 rdata_minfo.toWire(renderer);
189 vector<unsigned char> data;
190 UnitTestUtil::readWireData("rdata_minfo_toWire1.wire", data);
191 matchWireData(&data[0], data.size(),
192 renderer.getData(), renderer.getLength());
193
194 renderer.clear();
195 rdata_minfo2.toWire(renderer);
196 vector<unsigned char> data2;
197 UnitTestUtil::readWireData("rdata_minfo_toWire2.wire", data2);
198 matchWireData(&data2[0], data2.size(),
199 renderer.getData(), renderer.getLength());
200 }
201
TEST_F(Rdata_MINFO_Test,toText)202 TEST_F(Rdata_MINFO_Test, toText) {
203 EXPECT_EQ(minfo_txt, rdata_minfo.toText());
204 EXPECT_EQ(minfo_txt2, rdata_minfo2.toText());
205 }
206
TEST_F(Rdata_MINFO_Test,compare)207 TEST_F(Rdata_MINFO_Test, compare) {
208 // check reflexivity
209 EXPECT_EQ(0, rdata_minfo.compare(rdata_minfo));
210
211 // names must be compared in case-insensitive manner
212 EXPECT_EQ(0, rdata_minfo.compare(generic::MINFO("RMAILBOX.example.com. "
213 "emailbox.EXAMPLE.com.")));
214
215 // another MINFO whose rmailbox name is larger than that of rdata_minfo.
216 const generic::MINFO large1_minfo("zzzzzzzz.example.com. "
217 "emailbox.example.com.");
218 EXPECT_GT(0, rdata_minfo.compare(large1_minfo));
219 EXPECT_LT(0, large1_minfo.compare(rdata_minfo));
220
221 // another MINFO whose emailbox name is larger than that of rdata_minfo.
222 const generic::MINFO large2_minfo("rmailbox.example.com. "
223 "zzzzzzzzzzz.example.com.");
224 EXPECT_GT(0, rdata_minfo.compare(large2_minfo));
225 EXPECT_LT(0, large2_minfo.compare(rdata_minfo));
226
227 // comparison attempt between incompatible RR types should be rejected
228 EXPECT_THROW(rdata_minfo.compare(*RdataTest::rdata_nomatch), bad_cast);
229 }
230 }
231