rrset_unittest.cc 6.94 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Copyright (C) 2010  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.

// $Id$

JINMEI Tatuya's avatar
JINMEI Tatuya committed
17 18
#include <stdexcept>

19 20 21 22 23 24 25 26 27
#include <dns/buffer.h>
#include <dns/messagerenderer.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
#include <dns/rrttl.h>
#include <dns/rrset.h>
28 29 30

#include <gtest/gtest.h>

31
#include <dns/tests/unittest_util.h>
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

using isc::UnitTestUtil;

using namespace std;
using namespace isc::dns;
using namespace isc::dns::rdata;

namespace {
class RRsetTest : public ::testing::Test {
protected:
    RRsetTest() : buffer(0), renderer(buffer),
                  test_name("test.example.com"),
                  test_domain("example.com"),
                  test_nsname("ns.example.com"),
                  rrset_a(test_name, RRClass::IN(), RRType::A(), RRTTL(3600)),
JINMEI Tatuya's avatar
JINMEI Tatuya committed
47 48
                  rrset_a_empty(test_name, RRClass::IN(), RRType::A(),
                                RRTTL(3600)),
49
                  rrset_ns(test_domain, RRClass::IN(), RRType::NS(),
JINMEI Tatuya's avatar
JINMEI Tatuya committed
50 51 52 53 54 55 56
                           RRTTL(86400)),
                  rrset_ch_txt(test_domain, RRClass::CH(), RRType::TXT(),
                               RRTTL(0))
    {
        rrset_a.addRdata(in::A("192.0.2.1"));
        rrset_a.addRdata(in::A("192.0.2.2"));
    }
57 58 59 60 61 62 63

    OutputBuffer buffer;
    MessageRenderer renderer;
    Name test_name;
    Name test_domain;
    Name test_nsname;
    RRset rrset_a;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
64
    RRset rrset_a_empty;
65
    RRset rrset_ns;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
66
    RRset rrset_ch_txt;
67
    std::vector<unsigned char> wiredata;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
68 69 70 71 72

    // max number of Rdata objects added to a test RRset object.
    // this is an arbitrary chosen limit, but should be sufficiently large
    // in practice and reasonable even as an extreme test case.
    static const int MAX_RDATA_COUNT = 100;
73 74
};

JINMEI Tatuya's avatar
JINMEI Tatuya committed
75 76 77 78 79 80 81 82 83
TEST_F(RRsetTest, getRdataCount)
{
    for (int i = 0; i < MAX_RDATA_COUNT; ++i) {
        EXPECT_EQ(i, rrset_a_empty.getRdataCount());
        rrset_a_empty.addRdata(in::A("192.0.2.1"));
    }
}

TEST_F(RRsetTest, getName)
84
{
JINMEI Tatuya's avatar
JINMEI Tatuya committed
85 86 87 88 89 90 91 92 93
    EXPECT_EQ(test_name, rrset_a.getName());
    EXPECT_EQ(test_domain, rrset_ns.getName());
}

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

JINMEI Tatuya's avatar
JINMEI Tatuya committed
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
TEST_F(RRsetTest, 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(RRsetTest, 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(RRsetTest, setTTL)
{
    rrset_a.setTTL(RRTTL(86400));
    EXPECT_EQ(RRTTL(86400), rrset_a.getTTL());
    rrset_a.setTTL(RRTTL(0));
    EXPECT_EQ(RRTTL(0), rrset_a.getTTL());
}

TEST_F(RRsetTest, setName)
{
    rrset_a.setName(test_nsname);
    EXPECT_EQ(test_nsname, rrset_a.getName());
}

void
addRdataTestCommon(const RRset& rrset)
{
    EXPECT_EQ(2, rrset.getRdataCount());

    RdataIteratorPtr it = rrset.getRdataIterator();
129 130
    it->first();
    EXPECT_FALSE(it->isLast());
JINMEI Tatuya's avatar
JINMEI Tatuya committed
131
    EXPECT_EQ(0, it->getCurrent().compare(in::A("192.0.2.1")));
132 133
    it->next();
    EXPECT_FALSE(it->isLast());
JINMEI Tatuya's avatar
JINMEI Tatuya committed
134
    EXPECT_EQ(0, it->getCurrent().compare(in::A("192.0.2.2")));
135 136
    it->next();
    EXPECT_TRUE(it->isLast());
JINMEI Tatuya's avatar
JINMEI Tatuya committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
}

TEST_F(RRsetTest, addRdata)
{
    addRdataTestCommon(rrset_a);

    // Reference version of addRdata() doesn't allow to add a different
    // type of Rdata.
    EXPECT_THROW(rrset_a.addRdata(generic::NS(test_nsname)), std::bad_cast);
}

TEST_F(RRsetTest, addRdataPtr)
{
    rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(),
                                       rrset_a_empty.getClass(),
                                       "192.0.2.1"));
    rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(),
                                       rrset_a_empty.getClass(),
                                       "192.0.2.2"));

    addRdataTestCommon(rrset_a);

    // Pointer version of addRdata() doesn't type check and does allow to
    //add a different type of Rdata as a result.
    rrset_a_empty.addRdata(createRdata(RRType::NS(), RRClass::IN(),
                                       "ns.example.com"));
    EXPECT_EQ(3, rrset_a_empty.getRdataCount());
}

TEST_F(RRsetTest, iterator)
{
    // Iterator for an empty RRset.
    RdataIteratorPtr it = rrset_a_empty.getRdataIterator();
    it->first();
    EXPECT_TRUE(it->isLast());
172

JINMEI Tatuya's avatar
JINMEI Tatuya committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
    // Normal case (already tested, but do it again just in case)
    rrset_a_empty.addRdata(in::A("192.0.2.1"));
    rrset_a_empty.addRdata(in::A("192.0.2.2"));
    addRdataTestCommon(rrset_a_empty);

    // Rewind test: should be repeat the iteration by calling first().
    for (int i = 0; i < 2; ++i) {
        it = rrset_a_empty.getRdataIterator();
        it->first();
        EXPECT_FALSE(it->isLast());
        it->next();
        EXPECT_FALSE(it->isLast());
        it->next();
        EXPECT_TRUE(it->isLast());
    }
}

TEST_F(RRsetTest, toText)
{
192
    EXPECT_EQ("test.example.com. 3600 IN A 192.0.2.1\n"
JINMEI Tatuya's avatar
JINMEI Tatuya committed
193 194 195 196 197
              "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);
198 199 200 201 202 203
}

TEST_F(RRsetTest, toWireBuffer)
{
    rrset_a.toWire(buffer);

204
    UnitTestUtil::readWireData("rrset_toWire1", wiredata);
205 206
    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
                        buffer.getLength(), &wiredata[0], wiredata.size());
JINMEI Tatuya's avatar
JINMEI Tatuya committed
207 208 209 210

    // toWire() cannot be performed for an empty RRset.
    buffer.clear();
    EXPECT_THROW(rrset_a_empty.toWire(buffer), EmptyRRset);
211 212 213 214 215 216 217 218 219
}

TEST_F(RRsetTest, toWireRenderer)
{
    rrset_ns.addRdata(generic::NS(test_nsname));

    rrset_a.toWire(renderer);
    rrset_ns.toWire(renderer);

220
    UnitTestUtil::readWireData("rrset_toWire2", wiredata);
221 222
    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
                        buffer.getLength(), &wiredata[0], wiredata.size());
JINMEI Tatuya's avatar
JINMEI Tatuya committed
223 224 225 226

    // toWire() cannot be performed for an empty RRset.
    renderer.clear();
    EXPECT_THROW(rrset_a_empty.toWire(renderer), EmptyRRset);
227 228
}

JINMEI Tatuya's avatar
JINMEI Tatuya committed
229 230 231 232 233 234 235
// test operator<<.  We simply confirm it appends the result of toText().
TEST_F(RRsetTest, LeftShiftOperator)
{
    ostringstream oss;
    oss << rrset_a;
    EXPECT_EQ(rrset_a.toText(), oss.str());
}
236
}