|
@@ -12,12 +12,6 @@
|
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
// PERFORMANCE OF THIS SOFTWARE.
|
|
// PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
|
-#include <sstream>
|
|
|
|
-#include <vector>
|
|
|
|
-
|
|
|
|
-#include <boost/bind.hpp>
|
|
|
|
-#include <boost/foreach.hpp>
|
|
|
|
-
|
|
|
|
#include <exceptions/exceptions.h>
|
|
#include <exceptions/exceptions.h>
|
|
|
|
|
|
#include <dns/masterload.h>
|
|
#include <dns/masterload.h>
|
|
@@ -30,19 +24,30 @@
|
|
#include <dns/rrttl.h>
|
|
#include <dns/rrttl.h>
|
|
#include <dns/masterload.h>
|
|
#include <dns/masterload.h>
|
|
|
|
|
|
|
|
+#include <datasrc/client.h>
|
|
#include <datasrc/memory_datasrc.h>
|
|
#include <datasrc/memory_datasrc.h>
|
|
#include <datasrc/data_source.h>
|
|
#include <datasrc/data_source.h>
|
|
#include <datasrc/iterator.h>
|
|
#include <datasrc/iterator.h>
|
|
|
|
|
|
|
|
+#include "test_client.h"
|
|
|
|
+
|
|
#include <testutils/dnsmessage_test.h>
|
|
#include <testutils/dnsmessage_test.h>
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
+#include <boost/bind.hpp>
|
|
|
|
+#include <boost/foreach.hpp>
|
|
|
|
+#include <boost/shared_ptr.hpp>
|
|
|
|
+
|
|
|
|
+#include <sstream>
|
|
|
|
+#include <vector>
|
|
|
|
+
|
|
using namespace std;
|
|
using namespace std;
|
|
using namespace isc::dns;
|
|
using namespace isc::dns;
|
|
using namespace isc::dns::rdata;
|
|
using namespace isc::dns::rdata;
|
|
using namespace isc::datasrc;
|
|
using namespace isc::datasrc;
|
|
using namespace isc::testutils;
|
|
using namespace isc::testutils;
|
|
|
|
+using boost::shared_ptr;
|
|
|
|
|
|
namespace {
|
|
namespace {
|
|
// Commonly used result codes (Who should write the prefix all the time)
|
|
// Commonly used result codes (Who should write the prefix all the time)
|
|
@@ -285,14 +290,15 @@ setRRset(RRsetPtr rrset, vector<RRsetPtr*>::iterator& it) {
|
|
++it;
|
|
++it;
|
|
}
|
|
}
|
|
|
|
|
|
-ConstRRsetPtr
|
|
|
|
-textToRRset(const string& text_rrset, const RRClass& rrclass = RRClass::IN()) {
|
|
|
|
|
|
+RRsetPtr
|
|
|
|
+textToRRset(const string& text_rrset, const RRClass& rrclass = RRClass::IN(),
|
|
|
|
+ const Name& origin = Name::ROOT_NAME())
|
|
|
|
+{
|
|
stringstream ss(text_rrset);
|
|
stringstream ss(text_rrset);
|
|
RRsetPtr rrset;
|
|
RRsetPtr rrset;
|
|
vector<RRsetPtr*> rrsets;
|
|
vector<RRsetPtr*> rrsets;
|
|
rrsets.push_back(&rrset);
|
|
rrsets.push_back(&rrset);
|
|
- masterLoad(ss, Name::ROOT_NAME(), rrclass,
|
|
|
|
- boost::bind(setRRset, _1, rrsets.begin()));
|
|
|
|
|
|
+ masterLoad(ss, origin, rrclass, boost::bind(setRRset, _1, rrsets.begin()));
|
|
return (rrset);
|
|
return (rrset);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -398,6 +404,8 @@ public:
|
|
// Build test RRsets. Below, we construct an RRset for
|
|
// Build test RRsets. Below, we construct an RRset for
|
|
// each textual RR(s) of zone_data, and assign it to the corresponding
|
|
// each textual RR(s) of zone_data, and assign it to the corresponding
|
|
// rr_xxx.
|
|
// rr_xxx.
|
|
|
|
+ // Note that this contains an out-of-zone RR, and due to the
|
|
|
|
+ // validation check of masterLoad() used below, we cannot add SOA.
|
|
const RRsetData zone_data[] = {
|
|
const RRsetData zone_data[] = {
|
|
{"example.org. 300 IN NS ns.example.org.", &rr_ns_},
|
|
{"example.org. 300 IN NS ns.example.org.", &rr_ns_},
|
|
{"example.org. 300 IN A 192.0.2.1", &rr_a_},
|
|
{"example.org. 300 IN A 192.0.2.1", &rr_a_},
|
|
@@ -545,6 +553,8 @@ public:
|
|
ZoneFinder::FindOptions options = ZoneFinder::FIND_DEFAULT,
|
|
ZoneFinder::FindOptions options = ZoneFinder::FIND_DEFAULT,
|
|
bool check_wild_answer = false)
|
|
bool check_wild_answer = false)
|
|
{
|
|
{
|
|
|
|
+ SCOPED_TRACE("findTest for " + name.toText() + "/" + rrtype.toText());
|
|
|
|
+
|
|
if (zone_finder == NULL) {
|
|
if (zone_finder == NULL) {
|
|
zone_finder = &zone_finder_;
|
|
zone_finder = &zone_finder_;
|
|
}
|
|
}
|
|
@@ -1093,7 +1103,70 @@ TEST_F(InMemoryZoneFinderTest, load) {
|
|
|
|
|
|
// Try loading zone that is wrong in a different way
|
|
// Try loading zone that is wrong in a different way
|
|
EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
|
|
EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
|
|
- MasterLoadError);
|
|
|
|
|
|
+ MasterLoadError);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+TEST_F(InMemoryZoneFinderTest, loadFromIterator) {
|
|
|
|
+ // The initial test set doesn't have SOA at the apex.
|
|
|
|
+ findTest(origin_, RRType::SOA(), ZoneFinder::NXRRSET, false,
|
|
|
|
+ ConstRRsetPtr());
|
|
|
|
+
|
|
|
|
+ // The content of the new version of zone to be first installed to
|
|
|
|
+ // the SQLite3 data source, then to in-memory via SQLite3. The data are
|
|
|
|
+ // chosen to cover major check points of the implementation:
|
|
|
|
+ // - the previously non-existent record is added (SOA)
|
|
|
|
+ // - An RRSIG is given from the iterator before the RRset it covers
|
|
|
|
+ // (RRSIG for SOA, because they are sorted by name then rrtype as text)
|
|
|
|
+ // - An RRset containing multiple RRs (ns1/A)
|
|
|
|
+ // - RRSIGs for different owner names
|
|
|
|
+ stringstream ss;
|
|
|
|
+ const char* const soa_txt = "example.org. 300 IN SOA . . 0 0 0 0 0\n";
|
|
|
|
+ const char* const soa_sig_txt = "example.org. 300 IN RRSIG SOA 5 3 300 "
|
|
|
|
+ "20000101000000 20000201000000 12345 example.org. FAKEFAKE\n";
|
|
|
|
+ const char* const a_txt =
|
|
|
|
+ "ns1.example.org. 300 IN A 192.0.2.1\n"
|
|
|
|
+ "ns1.example.org. 300 IN A 192.0.2.2\n";
|
|
|
|
+ const char* const a_sig_txt = "ns1.example.org. 300 IN RRSIG A 5 3 300 "
|
|
|
|
+ "20000101000000 20000201000000 12345 example.org. FAKEFAKE\n";
|
|
|
|
+ ss << soa_txt << soa_sig_txt << a_txt << a_sig_txt;
|
|
|
|
+ shared_ptr<DataSourceClient> db_client = unittest::createSQLite3Client(
|
|
|
|
+ class_, origin_, TEST_DATA_BUILDDIR "/contexttest.sqlite3.copied", ss);
|
|
|
|
+ zone_finder_.load(*db_client->getIterator(origin_));
|
|
|
|
+
|
|
|
|
+ // The new content should be visible, including the previously-nonexistent
|
|
|
|
+ // SOA.
|
|
|
|
+ RRsetPtr expected_answer = textToRRset(soa_txt, RRClass::IN(), origin_);
|
|
|
|
+ expected_answer->addRRsig(textToRRset(soa_sig_txt));
|
|
|
|
+ findTest(origin_, RRType::SOA(), ZoneFinder::SUCCESS, true,
|
|
|
|
+ expected_answer);
|
|
|
|
+
|
|
|
|
+ expected_answer = textToRRset(a_txt);
|
|
|
|
+ expected_answer->addRRsig(textToRRset(a_sig_txt));
|
|
|
|
+ findTest(Name("ns1.example.org"), RRType::A(), ZoneFinder::SUCCESS, true,
|
|
|
|
+ expected_answer);
|
|
|
|
+
|
|
|
|
+ // File name should be (re)set to empty.
|
|
|
|
+ EXPECT_TRUE(zone_finder_.getFileName().empty());
|
|
|
|
+
|
|
|
|
+ // Loading the zone with an iterator separating RRs of the same RRset
|
|
|
|
+ // will fail because the resulting sequence doesn't meet assumptions of
|
|
|
|
+ // the (current) in-memory implementation.
|
|
|
|
+ EXPECT_THROW(zone_finder_.load(*db_client->getIterator(origin_, true)),
|
|
|
|
+ MasterLoadError);
|
|
|
|
+
|
|
|
|
+ // Load the zone from a file that contains more realistic data (borrowed
|
|
|
|
+ // from a different test). There's nothing special in this case for the
|
|
|
|
+ // purpose of this test, so it should just succeed.
|
|
|
|
+ db_client = unittest::createSQLite3Client(
|
|
|
|
+ class_, origin_, TEST_DATA_BUILDDIR "/contexttest.sqlite3.copied",
|
|
|
|
+ TEST_DATA_DIR "/contexttest.zone");
|
|
|
|
+ zone_finder_.load(*db_client->getIterator(origin_));
|
|
|
|
+
|
|
|
|
+ // just checking a couple of RRs in the new version of zone.
|
|
|
|
+ findTest(Name("mx1.example.org"), RRType::A(), ZoneFinder::SUCCESS, true,
|
|
|
|
+ textToRRset("mx1.example.org. 3600 IN A 192.0.2.10"));
|
|
|
|
+ findTest(Name("ns1.example.org"), RRType::AAAA(), ZoneFinder::SUCCESS,
|
|
|
|
+ true, textToRRset("ns1.example.org. 3600 IN AAAA 2001:db8::1"));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|