database_unittest.cc 57.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Copyright (C) 2011  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 <gtest/gtest.h>

#include <dns/name.h>
18
#include <dns/rrttl.h>
19
#include <dns/rrset.h>
20
#include <exceptions/exceptions.h>
21
22

#include <datasrc/database.h>
23
24
#include <datasrc/zone.h>
#include <datasrc/data_source.h>
25
#include <datasrc/iterator.h>
26

27
28
#include <testutils/dnsmessage_test.h>

29
#include <map>
30
31
32
33

using namespace isc::datasrc;
using namespace std;
using namespace boost;
34
using namespace isc::dns;
35
36
37
38

namespace {

/*
39
 * An accessor with minimum implementation, keeping the original
40
 * "NotImplemented" methods.
41
 */
42
class NopAccessor : public DatabaseAccessor {
43
public:
44
45
    NopAccessor() : database_name_("mock_database")
    { }
46

47
48
    virtual std::pair<bool, int> getZone(const std::string& name) const {
        if (name == "example.org.") {
49
            return (std::pair<bool, int>(true, 42));
50
        } else if (name == "null.example.org.") {
51
            return (std::pair<bool, int>(true, 13));
52
        } else if (name == "empty.example.org.") {
53
            return (std::pair<bool, int>(true, 0));
54
        } else if (name == "bad.example.org.") {
55
            return (std::pair<bool, int>(true, -1));
56
57
58
59
        } else {
            return (std::pair<bool, int>(false, 0));
        }
    }
60

61
62
63
64
    virtual const std::string& getDBName() const {
        return (database_name_);
    }

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
65
66
67
    virtual IteratorContextPtr getRecords(const std::string&, int, bool)
        const
        {
68
69
70
71
72
73
74
75
        isc_throw(isc::NotImplemented,
                  "This database datasource can't be iterated");
    };

    virtual IteratorContextPtr getAllRecords(int) const {
        isc_throw(isc::NotImplemented,
                  "This database datasource can't be iterated");
    };
76
77
78
private:
    const std::string database_name_;

79
80
};

81
82
83
84
85
86
87
/*
 * A virtual database connection that pretends it contains single zone --
 * example.org.
 *
 * It has the same getZone method as NopConnection, but it provides
 * implementation of the optional functionality.
 */
88
class MockAccessor : public NopAccessor {
89
public:
90
    MockAccessor()
91
92
93
    {
        fillData();
    }
94
private:
95
96
97
    class MockNameIteratorContext : public IteratorContext {
    public:
        MockNameIteratorContext(const MockAccessor& mock_accessor, int zone_id,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
98
                                const std::string& name, bool subdomains) :
99
            searched_name_(name), cur_record_(0)
100
        {
101
            // 'hardcoded' names to trigger exceptions
102
            // On these names some exceptions are thrown, to test the robustness
103
            // of the find() method.
104
105
106
107
108
109
110
111
112
            if (searched_name_ == "dsexception.in.search.") {
                isc_throw(DataSourceError, "datasource exception on search");
            } else if (searched_name_ == "iscexception.in.search.") {
                isc_throw(isc::Exception, "isc exception on search");
            } else if (searched_name_ == "basicexception.in.search.") {
                throw std::exception();
            }

            if (zone_id == 42) {
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
113
                if (subdomains) {
114
                    cur_name.clear();
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
115
116
117
118
119
120
121
122
123
124
125
126
                    // Just walk everything and check if it is a subdomain.
                    // If it is, just copy all data from there.
                    for (Domains::const_iterator
                         i(mock_accessor.records.begin());
                         i != mock_accessor.records.end(); ++ i) {
                        Name local(i->first);
                        if (local.compare(isc::dns::Name(name)).
                            getRelation() ==
                            isc::dns::NameComparisonResult::SUBDOMAIN) {
                            cur_name.insert(cur_name.end(), i->second.begin(),
                                            i->second.end());
                        }
127
                    }
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
128
                } else {
129
130
                    // we're not aiming for efficiency in this test, simply
                    // copy the relevant vector from records
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
131
132
133
134
135
136
                    if (mock_accessor.records.count(searched_name_) > 0) {
                        cur_name = mock_accessor.records.find(searched_name_)->
                            second;
                    } else {
                        cur_name.clear();
                    }
137
138
139
140
                }
            }
        }

141
        virtual bool getNext(std::string (&columns)[COLUMN_COUNT]) {
142
143
144
145
146
147
148
149
150
            if (searched_name_ == "dsexception.in.getnext.") {
                isc_throw(DataSourceError, "datasource exception on getnextrecord");
            } else if (searched_name_ == "iscexception.in.getnext.") {
                isc_throw(isc::Exception, "isc exception on getnextrecord");
            } else if (searched_name_ == "basicexception.in.getnext.") {
                throw std::exception();
            }

            if (cur_record_ < cur_name.size()) {
151
                for (size_t i = 0; i < COLUMN_COUNT; ++i) {
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
                    columns[i] = cur_name[cur_record_][i];
                }
                cur_record_++;
                return (true);
            } else {
                return (false);
            }
        }

    private:
        const std::string searched_name_;
        int cur_record_;
        std::vector< std::vector<std::string> > cur_name;
    };

167
168
169
170
171
172
173
    class MockIteratorContext : public IteratorContext {
    private:
        int step;
    public:
        MockIteratorContext() :
            step(0)
        { }
174
        virtual bool getNext(string (&data)[COLUMN_COUNT]) {
175
176
            switch (step ++) {
                case 0:
177
178
179
180
                    data[DatabaseAccessor::NAME_COLUMN] = "example.org";
                    data[DatabaseAccessor::TYPE_COLUMN] = "SOA";
                    data[DatabaseAccessor::TTL_COLUMN] = "300";
                    data[DatabaseAccessor::RDATA_COLUMN] = "ns1.example.org. admin.example.org. "
181
182
183
                        "1234 3600 1800 2419200 7200";
                    return (true);
                case 1:
184
185
186
187
                    data[DatabaseAccessor::NAME_COLUMN] = "x.example.org";
                    data[DatabaseAccessor::TYPE_COLUMN] = "A";
                    data[DatabaseAccessor::TTL_COLUMN] = "300";
                    data[DatabaseAccessor::RDATA_COLUMN] = "192.0.2.1";
188
189
                    return (true);
                case 2:
190
191
192
193
                    data[DatabaseAccessor::NAME_COLUMN] = "x.example.org";
                    data[DatabaseAccessor::TYPE_COLUMN] = "A";
                    data[DatabaseAccessor::TTL_COLUMN] = "300";
                    data[DatabaseAccessor::RDATA_COLUMN] = "192.0.2.2";
194
195
                    return (true);
                case 3:
196
197
198
199
                    data[DatabaseAccessor::NAME_COLUMN] = "x.example.org";
                    data[DatabaseAccessor::TYPE_COLUMN] = "AAAA";
                    data[DatabaseAccessor::TTL_COLUMN] = "300";
                    data[DatabaseAccessor::RDATA_COLUMN] = "2001:db8::1";
200
201
                    return (true);
                case 4:
202
203
204
205
                    data[DatabaseAccessor::NAME_COLUMN] = "x.example.org";
                    data[DatabaseAccessor::TYPE_COLUMN] = "AAAA";
                    data[DatabaseAccessor::TTL_COLUMN] = "300";
                    data[DatabaseAccessor::RDATA_COLUMN] = "2001:db8::2";
206
207
208
209
210
211
212
213
214
215
216
                    return (true);
                default:
                    ADD_FAILURE() <<
                        "Request past the end of iterator context";
                case 5:
                    return (false);
            }
        }
    };
    class EmptyIteratorContext : public IteratorContext {
    public:
217
        virtual bool getNext(string(&)[COLUMN_COUNT]) {
218
219
220
221
222
223
224
225
226
227
            return (false);
        }
    };
    class BadIteratorContext : public IteratorContext {
    private:
        int step;
    public:
        BadIteratorContext() :
            step(0)
        { }
228
        virtual bool getNext(string (&data)[COLUMN_COUNT]) {
229
230
            switch (step ++) {
                case 0:
231
232
233
234
                    data[DatabaseAccessor::NAME_COLUMN] = "x.example.org";
                    data[DatabaseAccessor::TYPE_COLUMN] = "A";
                    data[DatabaseAccessor::TTL_COLUMN] = "300";
                    data[DatabaseAccessor::RDATA_COLUMN] = "192.0.2.1";
235
236
                    return (true);
                case 1:
237
238
239
240
                    data[DatabaseAccessor::NAME_COLUMN] = "x.example.org";
                    data[DatabaseAccessor::TYPE_COLUMN] = "A";
                    data[DatabaseAccessor::TTL_COLUMN] = "301";
                    data[DatabaseAccessor::RDATA_COLUMN] = "192.0.2.2";
241
242
243
244
245
246
247
248
249
250
                    return (true);
                default:
                    ADD_FAILURE() <<
                        "Request past the end of iterator context";
                case 2:
                    return (false);
            }
        }
    };
public:
251
    virtual IteratorContextPtr getAllRecords(int id) const {
252
253
254
255
256
257
258
259
260
261
262
263
        if (id == 42) {
            return (IteratorContextPtr(new MockIteratorContext()));
        } else if (id == 13) {
            return (IteratorContextPtr());
        } else if (id == 0) {
            return (IteratorContextPtr(new EmptyIteratorContext()));
        } else if (id == -1) {
            return (IteratorContextPtr(new BadIteratorContext()));
        } else {
            isc_throw(isc::Unexpected, "Unknown zone ID");
        }
    }
264

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
265
266
267
    virtual IteratorContextPtr getRecords(const std::string& name, int id,
                                          bool subdomains) const
    {
268
        if (id == 42) {
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
269
270
            return (IteratorContextPtr(new MockNameIteratorContext(*this, id,
                name, subdomains)));
271
272
273
274
275
        } else {
            isc_throw(isc::Unexpected, "Unknown zone ID");
        }
    }

276
private:
277
278
    typedef std::map<std::string, std::vector< std::vector<std::string> > >
        Domains;
279
    // used as temporary storage during the building of the fake data
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
280
    Domains records;
281
282
283
284
285
    // used as temporary storage after searchForRecord() and during
    // getNextRecord() calls, as well as during the building of the
    // fake data
    std::vector< std::vector<std::string> > cur_name;

286
287
288
    // Adds one record to the current name in the database
    // The actual data will not be added to 'records' until
    // addCurName() is called
289
290
291
292
293
294
295
296
297
298
299
300
    void addRecord(const std::string& name,
                   const std::string& type,
                   const std::string& sigtype,
                   const std::string& rdata) {
        std::vector<std::string> columns;
        columns.push_back(name);
        columns.push_back(type);
        columns.push_back(sigtype);
        columns.push_back(rdata);
        cur_name.push_back(columns);
    }

301
302
303
    // Adds all records we just built with calls to addRecords
    // to the actual fake database. This will clear cur_name,
    // so we can immediately start adding new records.
304
    void addCurName(const std::string& name) {
305
        ASSERT_EQ(0, records.count(name));
306
307
308
309
310
        // Append the name to all of them
        for (std::vector<std::vector<std::string> >::iterator
             i(cur_name.begin()); i != cur_name.end(); ++ i) {
            i->push_back(name);
        }
311
312
313
314
        records[name] = cur_name;
        cur_name.clear();
    }

315
316
317
318
319
320
321
322
323
324
    // Fills the database with zone data.
    // This method constructs a number of resource records (with addRecord),
    // which will all be added for one domain name to the fake database
    // (with addCurName). So for instance the first set of calls create
    // data for the name 'www.example.org', which will consist of one A RRset
    // of one record, and one AAAA RRset of two records.
    // The order in which they are added is the order in which getNextRecord()
    // will return them (so we can test whether find() etc. support data that
    // might not come in 'normal' order)
    // It shall immediately fail if you try to add the same name twice.
325
    void fillData() {
326
        // some plain data
327
328
329
330
        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("AAAA", "3600", "", "2001:db8::1");
        addRecord("AAAA", "3600", "", "2001:db8::2");
        addCurName("www.example.org.");
331

332
333
334
335
336
        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("AAAA", "3600", "", "2001:db8::1");
        addRecord("A", "3600", "", "192.0.2.2");
        addCurName("www2.example.org.");

337
338
339
        addRecord("CNAME", "3600", "", "www.example.org.");
        addCurName("cname.example.org.");

340
341
342
        // some DNSSEC-'signed' data
        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
Jelte Jansen's avatar
Jelte Jansen committed
343
        addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12346 example.org. FAKEFAKEFAKE");
344
345
346
347
        addRecord("AAAA", "3600", "", "2001:db8::1");
        addRecord("AAAA", "3600", "", "2001:db8::2");
        addRecord("RRSIG", "3600", "", "AAAA 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addCurName("signed1.example.org.");
348
349
350
        addRecord("CNAME", "3600", "", "www.example.org.");
        addRecord("RRSIG", "3600", "", "CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addCurName("signedcname1.example.org.");
Jelte Jansen's avatar
Jelte Jansen committed
351
352
353
354
355
356
        // special case might fail; sig is for cname, which isn't there (should be ignored)
        // (ignoring of 'normal' other type is done above by www.)
        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addRecord("RRSIG", "3600", "", "CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addCurName("acnamesig1.example.org.");
357
358
359
360
361

        // let's pretend we have a database that is not careful
        // about the order in which it returns data
        addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addRecord("AAAA", "3600", "", "2001:db8::2");
Jelte Jansen's avatar
Jelte Jansen committed
362
        addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12346 example.org. FAKEFAKEFAKE");
363
364
365
366
367
        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("RRSIG", "3600", "", "AAAA 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addRecord("AAAA", "3600", "", "2001:db8::1");
        addCurName("signed2.example.org.");
        addRecord("RRSIG", "3600", "", "CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
368
369
        addRecord("CNAME", "3600", "", "www.example.org.");
        addCurName("signedcname2.example.org.");
370

Jelte Jansen's avatar
Jelte Jansen committed
371
372
373
374
375
376
377
378
379
380
        addRecord("RRSIG", "3600", "", "CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addCurName("acnamesig2.example.org.");

        addRecord("RRSIG", "3600", "", "CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addRecord("A", "3600", "", "192.0.2.1");
        addCurName("acnamesig3.example.org.");

381
382
383
384
385
386
387
        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("A", "360", "", "192.0.2.2");
        addCurName("ttldiff1.example.org.");
        addRecord("A", "360", "", "192.0.2.1");
        addRecord("A", "3600", "", "192.0.2.2");
        addCurName("ttldiff2.example.org.");

388
389
390
        // also add some intentionally bad data
        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("CNAME", "3600", "", "www.example.org.");
391
392
393
394
395
396
397
398
399
400
        addCurName("badcname1.example.org.");

        addRecord("CNAME", "3600", "", "www.example.org.");
        addRecord("A", "3600", "", "192.0.2.1");
        addCurName("badcname2.example.org.");

        addRecord("CNAME", "3600", "", "www.example.org.");
        addRecord("CNAME", "3600", "", "www.example2.org.");
        addCurName("badcname3.example.org.");

Jelte Jansen's avatar
Jelte Jansen committed
401
402
        addRecord("A", "3600", "", "bad");
        addCurName("badrdata.example.org.");
403

Jelte Jansen's avatar
Jelte Jansen committed
404
405
        addRecord("BAD_TYPE", "3600", "", "192.0.2.1");
        addCurName("badtype.example.org.");
406

Jelte Jansen's avatar
Jelte Jansen committed
407
408
        addRecord("A", "badttl", "", "192.0.2.1");
        addCurName("badttl.example.org.");
409
410
411
412
413
414
415
416

        addRecord("A", "badttl", "", "192.0.2.1");
        addRecord("RRSIG", "3600", "", "A 5 3 3600 somebaddata 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addCurName("badsig.example.org.");

        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("RRSIG", "3600", "TXT", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
        addCurName("badsigtype.example.org.");
417
418
419
420

        // Data for testing delegation (with NS and DNAME)
        addRecord("NS", "3600", "", "ns.example.com.");
        addRecord("NS", "3600", "", "ns.delegation.example.org.");
421
422
        addRecord("RRSIG", "3600", "", "NS 5 3 3600 20000101000000 "
                  "20000201000000 12345 example.org. FAKEFAKEFAKE");
423
424
425
        addCurName("delegation.example.org.");
        addRecord("A", "3600", "", "192.0.2.1");
        addCurName("ns.delegation.example.org.");
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
426
427
        addRecord("A", "3600", "", "192.0.2.1");
        addCurName("deep.below.delegation.example.org.");
428
429
430

        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("DNAME", "3600", "", "dname.example.com.");
431
432
        addRecord("RRSIG", "3600", "", "DNAME 5 3 3600 20000101000000 "
                  "20000201000000 12345 example.org. FAKEFAKEFAKE");
433
434
435
436
        addCurName("dname.example.org.");
        addRecord("A", "3600", "", "192.0.2.1");
        addCurName("below.dname.example.org.");

437
438
439
440
441
442
443
444
        // Broken NS
        addRecord("A", "3600", "", "192.0.2.1");
        addRecord("NS", "3600", "", "ns.example.com.");
        addCurName("brokenns1.example.org.");
        addRecord("NS", "3600", "", "ns.example.com.");
        addRecord("A", "3600", "", "192.0.2.1");
        addCurName("brokenns2.example.org.");

445
446
447
448
        // Now double DNAME, to test failure mode
        addRecord("DNAME", "3600", "", "dname1.example.com.");
        addRecord("DNAME", "3600", "", "dname2.example.com.");
        addCurName("baddname.example.org.");
449
450
451
452
453

        // Put some data into apex (including NS) so we can check our NS
        // doesn't break anything
        addRecord("NS", "3600", "", "ns.example.com.");
        addRecord("A", "3600", "", "192.0.2.1");
454
455
        addRecord("RRSIG", "3600", "", "NS 5 3 3600 20000101000000 "
                  "20000201000000 12345 example.org. FAKEFAKEFAKE");
456
        addCurName("example.org.");
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
457

458
459
460
        // This is because of empty domain test
        addRecord("A", "3600", "", "192.0.2.1");
        addCurName("a.b.example.org.");
461
462
463

        // Something for wildcards
        addRecord("A", "3600", "", "192.0.2.5");
464
        addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
465
466
467
        addCurName("*.wild.example.org.");
        addRecord("AAAA", "3600", "", "2001:db8::5");
        addCurName("cancel.here.wild.example.org.");
468
469
470
471
472
473
474
475
        addRecord("NS", "3600", "", "ns.example.com.");
        addCurName("delegatedwild.example.org.");
        addRecord("A", "3600", "", "192.0.2.5");
        addCurName("*.delegatedwild.example.org.");
        addRecord("A", "3600", "", "192.0.2.5");
        addCurName("wild.*.foo.example.org.");
        addRecord("A", "3600", "", "192.0.2.5");
        addCurName("wild.*.foo.*.bar.example.org.");
476
    }
477
478
};

479
480
// This tests the default getRecords behaviour, throwing NotImplemented
TEST(DatabaseConnectionTest, getRecords) {
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
481
    EXPECT_THROW(NopAccessor().getRecords(".", 1, false),
482
483
484
                 isc::NotImplemented);
}

485
486
// This tests the default getAllRecords behaviour, throwing NotImplemented
TEST(DatabaseConnectionTest, getAllRecords) {
487
    // The parameters don't matter
488
    EXPECT_THROW(NopAccessor().getAllRecords(1),
489
490
491
                 isc::NotImplemented);
}

492
493
494
495
496
497
498
499
500
501
class DatabaseClientTest : public ::testing::Test {
public:
    DatabaseClientTest() {
        createClient();
    }
    /*
     * We initialize the client from a function, so we can call it multiple
     * times per test.
     */
    void createClient() {
502
503
        current_database_ = new MockAccessor();
        client_.reset(new DatabaseClient(shared_ptr<DatabaseAccessor>(
504
             current_database_)));
505
506
    }
    // Will be deleted by client_, just keep the current value for comparison.
507
    MockAccessor* current_database_;
508
    shared_ptr<DatabaseClient> client_;
509
510
    const std::string database_name_;

511
512
    /**
     * Check the zone finder is a valid one and references the zone ID and
513
     * database available here.
514
515
516
517
518
519
520
521
     */
    void checkZoneFinder(const DataSourceClient::FindResult& zone) {
        ASSERT_NE(ZoneFinderPtr(), zone.zone_finder) << "No zone finder";
        shared_ptr<DatabaseClient::Finder> finder(
            dynamic_pointer_cast<DatabaseClient::Finder>(zone.zone_finder));
        ASSERT_NE(shared_ptr<DatabaseClient::Finder>(), finder) <<
            "Wrong type of finder";
        EXPECT_EQ(42, finder->zone_id());
522
        EXPECT_EQ(current_database_, &finder->database());
523
    }
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
524
525
526
527
528
529
530
531
532
533
534
535
536
537

    shared_ptr<DatabaseClient::Finder> getFinder() {
        DataSourceClient::FindResult zone(
            client_->findZone(Name("example.org")));
        EXPECT_EQ(result::SUCCESS, zone.code);
        shared_ptr<DatabaseClient::Finder> finder(
            dynamic_pointer_cast<DatabaseClient::Finder>(zone.zone_finder));
        EXPECT_EQ(42, finder->zone_id());

        return (finder);
    }

    std::vector<std::string> expected_rdatas_;
    std::vector<std::string> expected_sig_rdatas_;
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
};

TEST_F(DatabaseClientTest, zoneNotFound) {
    DataSourceClient::FindResult zone(client_->findZone(Name("example.com")));
    EXPECT_EQ(result::NOTFOUND, zone.code);
}

TEST_F(DatabaseClientTest, exactZone) {
    DataSourceClient::FindResult zone(client_->findZone(Name("example.org")));
    EXPECT_EQ(result::SUCCESS, zone.code);
    checkZoneFinder(zone);
}

TEST_F(DatabaseClientTest, superZone) {
    DataSourceClient::FindResult zone(client_->findZone(Name(
        "sub.example.org")));
    EXPECT_EQ(result::PARTIALMATCH, zone.code);
    checkZoneFinder(zone);
}

558
TEST_F(DatabaseClientTest, noAccessorException) {
Jelte Jansen's avatar
Jelte Jansen committed
559
560
561
    // We need a dummy variable here; some compiler would regard it a mere
    // declaration instead of an instantiation and make the test fail.
    EXPECT_THROW(DatabaseClient dummy((shared_ptr<DatabaseAccessor>())),
562
563
564
                 isc::InvalidParameter);
}

565
566
567
568
569
570
571
572
// If the zone doesn't exist, exception is thrown
TEST_F(DatabaseClientTest, noZoneIterator) {
    EXPECT_THROW(client_->getIterator(Name("example.com")), DataSourceError);
}

// If the zone doesn't exist and iteration is not implemented, it still throws
// the exception it doesn't exist
TEST_F(DatabaseClientTest, noZoneNotImplementedIterator) {
573
574
    EXPECT_THROW(DatabaseClient(boost::shared_ptr<DatabaseAccessor>(
        new NopAccessor())).getIterator(Name("example.com")),
575
576
577
578
                 DataSourceError);
}

TEST_F(DatabaseClientTest, notImplementedIterator) {
579
580
    EXPECT_THROW(DatabaseClient(shared_ptr<DatabaseAccessor>(
        new NopAccessor())).getIterator(Name("example.org")),
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
                 isc::NotImplemented);
}

// Pretend a bug in the connection and pass NULL as the context
// Should not crash, but gracefully throw
TEST_F(DatabaseClientTest, nullIteratorContext) {
    EXPECT_THROW(client_->getIterator(Name("null.example.org")),
                 isc::Unexpected);
}

// It doesn't crash or anything if the zone is completely empty
TEST_F(DatabaseClientTest, emptyIterator) {
    ZoneIteratorPtr it(client_->getIterator(Name("empty.example.org")));
    EXPECT_EQ(ConstRRsetPtr(), it->getNextRRset());
    // This is past the end, it should throw
    EXPECT_THROW(it->getNextRRset(), isc::Unexpected);
}

// Iterate trough a zone
TEST_F(DatabaseClientTest, iterator) {
    ZoneIteratorPtr it(client_->getIterator(Name("example.org")));
    ConstRRsetPtr rrset(it->getNextRRset());
    ASSERT_NE(ConstRRsetPtr(), rrset);
    EXPECT_EQ(Name("example.org"), rrset->getName());
    EXPECT_EQ(RRClass::IN(), rrset->getClass());
    EXPECT_EQ(RRType::SOA(), rrset->getType());
    EXPECT_EQ(RRTTL(300), rrset->getTTL());
    RdataIteratorPtr rit(rrset->getRdataIterator());
    ASSERT_FALSE(rit->isLast());
    rit->next();
    EXPECT_TRUE(rit->isLast());

    rrset = it->getNextRRset();
    ASSERT_NE(ConstRRsetPtr(), rrset);
    EXPECT_EQ(Name("x.example.org"), rrset->getName());
    EXPECT_EQ(RRClass::IN(), rrset->getClass());
    EXPECT_EQ(RRType::A(), rrset->getType());
    EXPECT_EQ(RRTTL(300), rrset->getTTL());
    rit = rrset->getRdataIterator();
    ASSERT_FALSE(rit->isLast());
    EXPECT_EQ("192.0.2.1", rit->getCurrent().toText());
    rit->next();
    ASSERT_FALSE(rit->isLast());
    EXPECT_EQ("192.0.2.2", rit->getCurrent().toText());
    rit->next();
    EXPECT_TRUE(rit->isLast());

    rrset = it->getNextRRset();
    ASSERT_NE(ConstRRsetPtr(), rrset);
    EXPECT_EQ(Name("x.example.org"), rrset->getName());
    EXPECT_EQ(RRClass::IN(), rrset->getClass());
    EXPECT_EQ(RRType::AAAA(), rrset->getType());
    EXPECT_EQ(RRTTL(300), rrset->getTTL());
    EXPECT_EQ(ConstRRsetPtr(), it->getNextRRset());
    rit = rrset->getRdataIterator();
    ASSERT_FALSE(rit->isLast());
    EXPECT_EQ("2001:db8::1", rit->getCurrent().toText());
    rit->next();
    ASSERT_FALSE(rit->isLast());
    EXPECT_EQ("2001:db8::2", rit->getCurrent().toText());
    rit->next();
    EXPECT_TRUE(rit->isLast());
}

// This has inconsistent TTL in the set (the rest, like nonsense in
// the data is handled in rdata itself).
TEST_F(DatabaseClientTest, badIterator) {
648
    // It should not throw, but get the lowest one of them
649
    ZoneIteratorPtr it(client_->getIterator(Name("bad.example.org")));
650
    EXPECT_EQ(it->getNextRRset()->getTTL(), isc::dns::RRTTL(300));
651
652
}

653
654
655
656
657
658
659
660
// checks if the given rrset matches the
// given name, class, type and rdatas
void
checkRRset(isc::dns::ConstRRsetPtr rrset,
           const isc::dns::Name& name,
           const isc::dns::RRClass& rrclass,
           const isc::dns::RRType& rrtype,
           const isc::dns::RRTTL& rrttl,
661
           const std::vector<std::string>& rdatas) {
662
663
664
665
666
667
668
669
670
671
    isc::dns::RRsetPtr expected_rrset(
        new isc::dns::RRset(name, rrclass, rrtype, rrttl));
    for (unsigned int i = 0; i < rdatas.size(); ++i) {
        expected_rrset->addRdata(
            isc::dns::rdata::createRdata(rrtype, rrclass,
                                         rdatas[i]));
    }
    isc::testutils::rrsetCheck(expected_rrset, rrset);
}

672
673
674
675
676
void
doFindTest(shared_ptr<DatabaseClient::Finder> finder,
           const isc::dns::Name& name,
           const isc::dns::RRType& type,
           const isc::dns::RRType& expected_type,
677
           const isc::dns::RRTTL expected_ttl,
678
           ZoneFinder::Result expected_result,
679
           const std::vector<std::string>& expected_rdatas,
680
           const std::vector<std::string>& expected_sig_rdatas,
681
682
           const isc::dns::Name& expected_name = isc::dns::Name::ROOT_NAME(),
           const ZoneFinder::FindOptions options = ZoneFinder::FIND_DEFAULT)
683
{
684
    SCOPED_TRACE("doFindTest " + name.toText() + " " + type.toText());
685
    ZoneFinder::FindResult result =
686
        finder->find(name, type, NULL, options);
687
    ASSERT_EQ(expected_result, result.code) << name << " " << type;
688
    if (!expected_rdatas.empty()) {
689
690
691
        checkRRset(result.rrset, expected_name != Name(".") ? expected_name :
                   name, finder->getClass(), expected_type, expected_ttl,
                   expected_rdatas);
692

693
        if (!expected_sig_rdatas.empty()) {
694
695
696
697
            checkRRset(result.rrset->getRRsig(), expected_name != Name(".") ?
                       expected_name : name, finder->getClass(),
                       isc::dns::RRType::RRSIG(), expected_ttl,
                       expected_sig_rdatas);
698
699
700
701
702
703
704
705
        } else {
            EXPECT_EQ(isc::dns::RRsetPtr(), result.rrset->getRRsig());
        }
    } else {
        EXPECT_EQ(isc::dns::RRsetPtr(), result.rrset);
    }
}

706
TEST_F(DatabaseClientTest, find) {
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
707
    shared_ptr<DatabaseClient::Finder> finder(getFinder());
708

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
709
710
711
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
712
713
    doFindTest(finder, isc::dns::Name("www.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
714
               isc::dns::RRTTL(3600),
715
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
716
               expected_rdatas_, expected_sig_rdatas_);
717

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
718
719
720
721
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
    expected_rdatas_.push_back("192.0.2.2");
722
723
724
    doFindTest(finder, isc::dns::Name("www2.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
               isc::dns::RRTTL(3600),
725
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
726
               expected_rdatas_, expected_sig_rdatas_);
727

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
728
729
730
731
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("2001:db8::1");
    expected_rdatas_.push_back("2001:db8::2");
732
733
    doFindTest(finder, isc::dns::Name("www.example.org."),
               isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(),
734
               isc::dns::RRTTL(3600),
735
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
736
               expected_rdatas_, expected_sig_rdatas_);
737

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
738
739
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
740
741
    doFindTest(finder, isc::dns::Name("www.example.org."),
               isc::dns::RRType::TXT(), isc::dns::RRType::TXT(),
742
               isc::dns::RRTTL(3600),
743
               ZoneFinder::NXRRSET,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
744
               expected_rdatas_, expected_sig_rdatas_);
745

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
746
747
748
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("www.example.org.");
749
750
    doFindTest(finder, isc::dns::Name("cname.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::CNAME(),
751
               isc::dns::RRTTL(3600),
752
               ZoneFinder::CNAME,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
753
               expected_rdatas_, expected_sig_rdatas_);
754

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
755
756
757
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("www.example.org.");
758
759
760
    doFindTest(finder, isc::dns::Name("cname.example.org."),
               isc::dns::RRType::CNAME(), isc::dns::RRType::CNAME(),
               isc::dns::RRTTL(3600),
761
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
762
               expected_rdatas_, expected_sig_rdatas_);
763

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
764
765
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
766
767
    doFindTest(finder, isc::dns::Name("doesnotexist.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
768
               isc::dns::RRTTL(3600),
769
               ZoneFinder::NXDOMAIN,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
770
               expected_rdatas_, expected_sig_rdatas_);
771

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
772
773
774
775
776
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
    expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
    expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 20000201000000 12346 example.org. FAKEFAKEFAKE");
777
778
    doFindTest(finder, isc::dns::Name("signed1.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
779
               isc::dns::RRTTL(3600),
780
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
781
               expected_rdatas_, expected_sig_rdatas_);
782

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
783
784
785
786
787
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("2001:db8::1");
    expected_rdatas_.push_back("2001:db8::2");
    expected_sig_rdatas_.push_back("AAAA 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
788
789
    doFindTest(finder, isc::dns::Name("signed1.example.org."),
               isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(),
790
               isc::dns::RRTTL(3600),
791
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
792
               expected_rdatas_, expected_sig_rdatas_);
793

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
794
795
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
796
797
    doFindTest(finder, isc::dns::Name("signed1.example.org."),
               isc::dns::RRType::TXT(), isc::dns::RRType::TXT(),
798
               isc::dns::RRTTL(3600),
799
               ZoneFinder::NXRRSET,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
800
               expected_rdatas_, expected_sig_rdatas_);
801

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
802
803
804
805
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("www.example.org.");
    expected_sig_rdatas_.push_back("CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
806
807
    doFindTest(finder, isc::dns::Name("signedcname1.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::CNAME(),
808
               isc::dns::RRTTL(3600),
809
               ZoneFinder::CNAME,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
810
               expected_rdatas_, expected_sig_rdatas_);
811

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
812
813
814
815
816
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
    expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
    expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 20000201000000 12346 example.org. FAKEFAKEFAKE");
817
818
    doFindTest(finder, isc::dns::Name("signed2.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
819
               isc::dns::RRTTL(3600),
820
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
821
               expected_rdatas_, expected_sig_rdatas_);
822

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
823
824
825
826
827
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("2001:db8::2");
    expected_rdatas_.push_back("2001:db8::1");
    expected_sig_rdatas_.push_back("AAAA 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
828
829
    doFindTest(finder, isc::dns::Name("signed2.example.org."),
               isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(),
830
               isc::dns::RRTTL(3600),
831
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
832
               expected_rdatas_, expected_sig_rdatas_);
833

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
834
835
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
836
837
    doFindTest(finder, isc::dns::Name("signed2.example.org."),
               isc::dns::RRType::TXT(), isc::dns::RRType::TXT(),
838
               isc::dns::RRTTL(3600),
839
               ZoneFinder::NXRRSET,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
840
               expected_rdatas_, expected_sig_rdatas_);
841

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
842
843
844
845
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("www.example.org.");
    expected_sig_rdatas_.push_back("CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
846
847
    doFindTest(finder, isc::dns::Name("signedcname2.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::CNAME(),
848
               isc::dns::RRTTL(3600),
849
               ZoneFinder::CNAME,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
850
               expected_rdatas_, expected_sig_rdatas_);
851

852

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
853
854
855
856
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
    expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
Jelte Jansen's avatar
Jelte Jansen committed
857
858
    doFindTest(finder, isc::dns::Name("acnamesig1.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
859
               isc::dns::RRTTL(3600),
860
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
861
               expected_rdatas_, expected_sig_rdatas_);
862

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
863
864
865
866
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
    expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
Jelte Jansen's avatar
Jelte Jansen committed
867
868
    doFindTest(finder, isc::dns::Name("acnamesig2.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
869
               isc::dns::RRTTL(3600),
870
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
871
               expected_rdatas_, expected_sig_rdatas_);
872

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
873
874
875
876
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
    expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
Jelte Jansen's avatar
Jelte Jansen committed
877
878
    doFindTest(finder, isc::dns::Name("acnamesig3.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
879
               isc::dns::RRTTL(3600),
880
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
881
               expected_rdatas_, expected_sig_rdatas_);
Jelte Jansen's avatar
Jelte Jansen committed
882

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
883
884
885
886
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
    expected_rdatas_.push_back("192.0.2.2");
887
888
889
    doFindTest(finder, isc::dns::Name("ttldiff1.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
               isc::dns::RRTTL(360),
890
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
891
               expected_rdatas_, expected_sig_rdatas_);
892

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
893
894
895
896
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
    expected_rdatas_.push_back("192.0.2.2");
897
898
899
    doFindTest(finder, isc::dns::Name("ttldiff2.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
               isc::dns::RRTTL(360),
900
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
901
               expected_rdatas_, expected_sig_rdatas_);
902

903

904
905
906
907
908
    EXPECT_THROW(finder->find(isc::dns::Name("badcname1.example.org."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 DataSourceError);
    EXPECT_THROW(finder->find(isc::dns::Name("badcname2.example.org."),
909
910
911
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 DataSourceError);
912
    EXPECT_THROW(finder->find(isc::dns::Name("badcname3.example.org."),
913
914
915
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 DataSourceError);
Jelte Jansen's avatar
Jelte Jansen committed
916
917
918
919
920
921
922
923
924
925
926
927
    EXPECT_THROW(finder->find(isc::dns::Name("badrdata.example.org."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 DataSourceError);
    EXPECT_THROW(finder->find(isc::dns::Name("badtype.example.org."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 DataSourceError);
    EXPECT_THROW(finder->find(isc::dns::Name("badttl.example.org."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 DataSourceError);
928
929
930
931
932
933
934
935
936
937
938
939
940
    EXPECT_THROW(finder->find(isc::dns::Name("badsig.example.org."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 DataSourceError);

    // Trigger the hardcoded exceptions and see if find() has cleaned up
    EXPECT_THROW(finder->find(isc::dns::Name("dsexception.in.search."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 DataSourceError);
    EXPECT_THROW(finder->find(isc::dns::Name("iscexception.in.search."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
941
                 isc::Exception);
942
943
944
945
    EXPECT_THROW(finder->find(isc::dns::Name("basicexception.in.search."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 std::exception);
946

947
948
949
950
951
952
953
    EXPECT_THROW(finder->find(isc::dns::Name("dsexception.in.getnext."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 DataSourceError);
    EXPECT_THROW(finder->find(isc::dns::Name("iscexception.in.getnext."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
954
                 isc::Exception);
955
956
957
958
959
960
961
962
    EXPECT_THROW(finder->find(isc::dns::Name("basicexception.in.getnext."),
                                              isc::dns::RRType::A(),
                                              NULL, ZoneFinder::FIND_DEFAULT),
                 std::exception);

    // This RRSIG has the wrong sigtype field, which should be
    // an error if we decide to keep using that field
    // Right now the field is ignored, so it does not error
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
963
964
965
966
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
    expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
967
968
969
    doFindTest(finder, isc::dns::Name("badsigtype.example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
               isc::dns::RRTTL(3600),
970
               ZoneFinder::SUCCESS,
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
971
               expected_rdatas_, expected_sig_rdatas_);
972
973
}

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
974
975
TEST_F(DatabaseClientTest, findDelegation) {
    shared_ptr<DatabaseClient::Finder> finder(getFinder());
976

977
978
    // The apex should not be considered delegation point and we can access
    // data
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
979
980
981
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("192.0.2.1");
982
983
    doFindTest(finder, isc::dns::Name("example.org."),
               isc::dns::RRType::A(), isc::dns::RRType::A(),
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
984
985
               isc::dns::RRTTL(3600), ZoneFinder::SUCCESS, expected_rdatas_,
               expected_sig_rdatas_);
986

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
987
988
989
    expected_rdatas_.clear();
    expected_rdatas_.push_back("ns.example.com.");
    expected_sig_rdatas_.push_back("NS 5 3 3600 20000101000000 20000201000000 "
990
                                  "12345 example.org. FAKEFAKEFAKE");
991
992
    doFindTest(finder, isc::dns::Name("example.org."),
               isc::dns::RRType::NS(), isc::dns::RRType::NS(),
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
993
994
               isc::dns::RRTTL(3600), ZoneFinder::SUCCESS, expected_rdatas_,
               expected_sig_rdatas_);
995

996
997
    // Check when we ask for something below delegation point, we get the NS
    // (Both when the RRset there exists and doesn't)
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
998
999
1000
    expected_rdatas_.clear();
    expected_sig_rdatas_.clear();
    expected_rdatas_.push_back("ns.example.com.");