rbnode_rrset_unittest.cc 8.73 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <stdexcept>

#include <exceptions/exceptions.h>
#include <dns/rdataclass.h>
#include <datasrc/rbnode_rrset.h>
20
#include <testutils/dnsmessage_test.h>
21
22
23
24
25
26
27
28
29

#include <gtest/gtest.h>

#include <dns/tests/unittest_util.h>

using isc::UnitTestUtil;

using namespace isc;
using namespace isc::datasrc;
30
using namespace isc::datasrc::internal;
31
32
using namespace isc::dns;
using namespace isc::dns::rdata;
33
using namespace isc::testutils;
34
using namespace isc::util;
35
using namespace std;
36

37
// These tests are very similar to those for RRset - indeed, this file was
38
39
40
41
42
43
// created from those tests.  However, the significant difference in behaviour
// between RRset and RBNodeRRset - that the "set" methods in the latter mostly
// result in exceptions being thrown - preclude use of full type
// parameterisation of the tests.

namespace {
44
const char* const RRSIG_TXT =
45
46
47
48
49
50
    "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
    "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
    "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
    "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
    "f49t+sXKPzbipN9g+s1ZPiIyofc=";

51
52
53
54
55
56
57
58
59
60
61
62
63
class RBNodeRRsetTest : public ::testing::Test {
protected:
    RBNodeRRsetTest() :
        test_name("test.example.com"),
        test_domain("example.com"),
        test_nsname("ns.example.com"),
        rrset_a(ConstRRsetPtr(new RRset(
                test_name, RRClass::IN(), RRType::A(), RRTTL(3600)))),
        rrset_a_empty(ConstRRsetPtr(new RRset(
                      test_name, RRClass::IN(), RRType::A(), RRTTL(3600)))),
        rrset_ns(ConstRRsetPtr(new RRset(
                 test_domain, RRClass::IN(), RRType::NS(), RRTTL(86400)))),
        rrset_ch_txt(ConstRRsetPtr(new RRset(
64
65
66
67
                     test_domain, RRClass::CH(), RRType::TXT(), RRTTL(0)))),
        rrset_siga(new RRset(test_name, RRClass::IN(), RRType::RRSIG(),
                   RRTTL(3600)))

68
    {
69
        // Add a couple of Rdata elements to the A RRset.  The easiest way to
70
71
        // do this is to override the "const" restrictions.  As this is a test,
        // we don't feel too bad about doing so.
72
        AbstractRRset* a_rrset =
73
            const_cast<AbstractRRset*>(rrset_a.getUnderlyingRRset().get());
74
75
76
77
78
79
        a_rrset->addRdata(in::A("192.0.2.1"));
        a_rrset->addRdata(in::A("192.0.2.2"));

        // Create the RRSIG corresponding to the rrset_a record.  The RDATA
        // won't match the A record it covers, although it is internally
        // self-consistent.
80
81
        AbstractRRset* sig_rrset =
            const_cast<AbstractRRset*>(rrset_siga.get());
82
        sig_rrset->addRdata(generic::RRSIG(RRSIG_TXT));
83
84
    }

85
86
87
    const Name test_name;
    const Name test_domain;
    const Name test_nsname;
88

89
90
    RBNodeRRset rrset_a;
    RBNodeRRset rrset_a_empty;
91
92
    const RBNodeRRset rrset_ns;
    const RBNodeRRset rrset_ch_txt;
93

94
    ConstRRsetPtr rrset_siga;
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
};

TEST_F(RBNodeRRsetTest, getRdataCount) {
    EXPECT_EQ(0, rrset_a_empty.getRdataCount());
    EXPECT_EQ(2, rrset_a.getRdataCount());
}

TEST_F(RBNodeRRsetTest, getName) {
    EXPECT_EQ(test_name, rrset_a.getName());
    EXPECT_EQ(test_domain, rrset_ns.getName());
}

TEST_F(RBNodeRRsetTest, getClass) {
    EXPECT_EQ(RRClass("IN"), rrset_a.getClass());
    EXPECT_EQ(RRClass("CH"), rrset_ch_txt.getClass());
}

TEST_F(RBNodeRRsetTest, getType) {
    EXPECT_EQ(RRType("A"), rrset_a.getType());
    EXPECT_EQ(RRType("NS"), rrset_ns.getType());
    EXPECT_EQ(RRType("TXT"), rrset_ch_txt.getType());
}

TEST_F(RBNodeRRsetTest, getTTL) {
    EXPECT_EQ(RRTTL(3600), rrset_a.getTTL());
    EXPECT_EQ(RRTTL(86400), rrset_ns.getTTL());
    EXPECT_EQ(RRTTL(0), rrset_ch_txt.getTTL());
}

TEST_F(RBNodeRRsetTest, setName) {
    EXPECT_THROW(rrset_a.setName(test_nsname), NotImplemented);
}

TEST_F(RBNodeRRsetTest, setTTL) {
    EXPECT_THROW(rrset_a.setTTL(RRTTL(86400)), NotImplemented);
}

TEST_F(RBNodeRRsetTest, toText) {
    EXPECT_EQ("test.example.com. 3600 IN A 192.0.2.1\n"
              "test.example.com. 3600 IN A 192.0.2.2\n",
              rrset_a.toText());

    // toText() cannot be performed for an empty RRset.
    EXPECT_THROW(rrset_a_empty.toText(), EmptyRRset);
}

141
142
143
144
145
146
147
148
149
150
// Note: although the next two tests are essentially the same and used common
// test code, they use different test data: the MessageRenderer produces
// compressed wire data whereas the OutputBuffer does not.

template <typename T>
void
performToWireTest(T& dataHolder, const RBNodeRRset& rrset,
                  const RBNodeRRset& rrset_empty, const char* testdata)
{
    rrset.toWire(dataHolder);
151

152
    std::vector<unsigned char> wiredata;
153
154
155
    UnitTestUtil::readWireData(testdata, wiredata);
    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, dataHolder.getData(),
                        dataHolder.getLength(), &wiredata[0], wiredata.size());
156
157

    // toWire() cannot be performed for an empty RRset.
158
159
    dataHolder.clear();
    EXPECT_THROW(rrset_empty.toWire(dataHolder), EmptyRRset);
160
161
}

162
TEST_F(RBNodeRRsetTest, toWireRenderer) {
163
    MessageRenderer renderer;
164
165
    performToWireTest(renderer, rrset_a, rrset_a_empty, "rrset_toWire2");
}
166

167
168
169
TEST_F(RBNodeRRsetTest, toWireBuffer) {
    OutputBuffer buffer(0);
    performToWireTest(buffer, rrset_a, rrset_a_empty, "rrset_toWire1");
170
171
172
173
174
}

TEST_F(RBNodeRRsetTest, addRdata) {
    EXPECT_THROW(rrset_a.addRdata(in::A("192.0.2.3")), NotImplemented);

175
    // Check the same goes for trying to add the wrong type of data
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    EXPECT_THROW(rrset_a.addRdata(generic::NS(test_nsname)), NotImplemented);
}

TEST_F(RBNodeRRsetTest, addRdataPtr) {
    EXPECT_THROW(rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(),
                                                    rrset_a_empty.getClass(),
                                                    "192.0.2.1")),
                 NotImplemented);
}

TEST_F(RBNodeRRsetTest, getRDataIterator) {
    RdataIteratorPtr it = rrset_a.getRdataIterator();
    for (int i = 0; i < 2; ++i) {
        ASSERT_FALSE(it->isLast());
        ASSERT_EQ(0, it->getCurrent().compare(in::A("192.0.2.1")));

        it->next();
        ASSERT_FALSE(it->isLast());
        ASSERT_EQ(0, it->getCurrent().compare(in::A("192.0.2.2")));

        it->next();
        ASSERT_TRUE(it->isLast());

        // Should be able repeat the iteration by calling first().
        it->first();
    }
}

// test operator<<.  We simply confirm it appends the result of toText().
TEST_F(RBNodeRRsetTest, LeftShiftOperator) {
    ostringstream oss;
    oss << rrset_a;
    EXPECT_EQ("test.example.com. 3600 IN A 192.0.2.1\n"
              "test.example.com. 3600 IN A 192.0.2.2\n", oss.str());
}

212
213
214
// addRRSIG tests.
TEST_F(RBNodeRRsetTest, addRRsigConstRdataPointer) {
    EXPECT_FALSE(rrset_a.getRRsig());
215
216
217
    ConstRdataPtr data = createRdata(rrset_siga->getType(),
                                     rrset_siga->getClass(), RRSIG_TXT);
    rrset_a.addRRsig(data);
218
    rrsetCheck(rrset_siga, rrset_a.getRRsig());
219
220
221
222
223
}

TEST_F(RBNodeRRsetTest, addRRsigRdataPointer) {
    EXPECT_FALSE(rrset_a.getRRsig());
    RdataPtr data = createRdata(rrset_siga->getType(), rrset_siga->getClass(),
224
225
                                RRSIG_TXT);
    rrset_a.addRRsig(data);
226
    rrsetCheck(rrset_siga, rrset_a.getRRsig());
227
228
229
230
}

TEST_F(RBNodeRRsetTest, addRRsigAbstractRRset) {
    EXPECT_FALSE(rrset_a.getRRsig());
231
    rrset_a.addRRsig(*(rrset_siga.get()));
232
    rrsetCheck(rrset_siga, rrset_a.getRRsig());
233
234
235
236
}

TEST_F(RBNodeRRsetTest, addRRsigConstantRRsetPointer) {
    EXPECT_FALSE(rrset_a.getRRsig());
237
    rrset_a.addRRsig(rrset_siga);
238
    rrsetCheck(rrset_siga, rrset_a.getRRsig());
239
240
241
242
243
244
245
}

TEST_F(RBNodeRRsetTest, addRRsigRRsetPointer) {
    EXPECT_FALSE(rrset_a.getRRsig());
    RRsetPtr rrsig(new RRset(test_name, RRClass::IN(), RRType::RRSIG(),
                   RRTTL(3600)));
    rrsig->addRdata(generic::RRSIG(RRSIG_TXT));
246
    rrset_a.addRRsig(rrsig);
247
    rrsetCheck(rrset_siga, rrset_a.getRRsig());
248
249
250
251
}

TEST_F(RBNodeRRsetTest, removeRRsig) {
    EXPECT_FALSE(rrset_a.getRRsig());
252
    rrset_a.addRRsig(*(rrset_siga.get()));
253
254
255
256
257
    EXPECT_TRUE(rrset_a.getRRsig());
    rrset_a.removeRRsig();
    EXPECT_FALSE(rrset_a.getRRsig());
}

258
}   // Anonymous namespace