12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178 |
- // 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 <datasrc/client_list.h>
- #include <datasrc/client.h>
- #include <datasrc/zone_iterator.h>
- #include <datasrc/data_source.h>
- #include <datasrc/memory/memory_client.h>
- #include <datasrc/memory/zone_table_segment.h>
- #include <datasrc/memory/zone_finder.h>
- #include <datasrc/memory/zone_writer.h>
- #include <dns/rrclass.h>
- #include <dns/rrttl.h>
- #include <dns/rdataclass.h>
- #include <gtest/gtest.h>
- #include <boost/shared_ptr.hpp>
- #include <set>
- #include <fstream>
- using namespace isc::datasrc;
- using isc::datasrc::memory::InMemoryClient;
- using isc::datasrc::memory::ZoneTableSegment;
- using isc::datasrc::memory::InMemoryZoneFinder;
- using namespace isc::data;
- using namespace isc::dns;
- // don't import the entire boost namespace. It will unexpectedly hide uintXX_t
- // for some systems.
- using boost::shared_ptr;
- using namespace std;
- namespace {
- // A test data source. It pretends it has some zones.
- class MockDataSourceClient : public DataSourceClient {
- public:
- class Finder : public ZoneFinder {
- public:
- Finder(const Name& origin) :
- origin_(origin)
- {}
- Name getOrigin() const { return (origin_); }
- // The rest is not to be called, so just have them
- RRClass getClass() const {
- isc_throw(isc::NotImplemented, "Not implemented");
- }
- shared_ptr<Context> find(const Name&, const RRType&,
- const FindOptions)
- {
- isc_throw(isc::NotImplemented, "Not implemented");
- }
- shared_ptr<Context> findAll(const Name&,
- vector<ConstRRsetPtr>&,
- const FindOptions)
- {
- isc_throw(isc::NotImplemented, "Not implemented");
- }
- FindNSEC3Result findNSEC3(const Name&, bool) {
- isc_throw(isc::NotImplemented, "Not implemented");
- }
- private:
- Name origin_;
- };
- class Iterator : public ZoneIterator {
- public:
- Iterator(const Name& origin, bool include_a) :
- origin_(origin),
- soa_(new RRset(origin_, RRClass::IN(), RRType::SOA(),
- RRTTL(3600)))
- {
- // The RData here is bogus, but it is not used to anything. There
- // just needs to be some.
- soa_->addRdata(rdata::generic::SOA(Name::ROOT_NAME(),
- Name::ROOT_NAME(),
- 0, 0, 0, 0, 0));
- rrsets_.push_back(soa_);
- RRsetPtr rrset(new RRset(origin_, RRClass::IN(), RRType::NS(),
- RRTTL(3600)));
- rrset->addRdata(rdata::generic::NS(Name::ROOT_NAME()));
- rrsets_.push_back(rrset);
- if (include_a) {
- // Dummy A rrset. This is used for checking zone data
- // after reload.
- rrset.reset(new RRset(Name("tstzonedata").concatenate(origin_),
- RRClass::IN(), RRType::A(),
- RRTTL(3600)));
- rrset->addRdata(rdata::in::A("192.0.2.1"));
- rrsets_.push_back(rrset);
- }
- rrsets_.push_back(ConstRRsetPtr());
- it_ = rrsets_.begin();
- }
- virtual isc::dns::ConstRRsetPtr getNextRRset() {
- ConstRRsetPtr result = *it_;
- ++it_;
- return (result);
- }
- virtual isc::dns::ConstRRsetPtr getSOA() const {
- return (soa_);
- }
- private:
- const Name origin_;
- const RRsetPtr soa_;
- std::vector<ConstRRsetPtr> rrsets_;
- std::vector<ConstRRsetPtr>::const_iterator it_;
- };
- // Constructor from a list of zones.
- MockDataSourceClient(const char* zone_names[]) :
- have_a_(true), use_baditerator_(true)
- {
- for (const char** zone(zone_names); *zone; ++zone) {
- zones.insert(Name(*zone));
- }
- }
- // Constructor from configuration. The list of zones will be empty, but
- // it will keep the configuration inside for further inspection.
- MockDataSourceClient(const string& type,
- const ConstElementPtr& configuration) :
- type_(type),
- configuration_(configuration),
- have_a_(true), use_baditerator_(true)
- {
- EXPECT_NE("MasterFiles", type) << "MasterFiles is a special case "
- "and it never should be created as a data source client";
- if (configuration_->getType() == Element::list) {
- for (size_t i(0); i < configuration_->size(); ++i) {
- zones.insert(Name(configuration_->get(i)->stringValue()));
- }
- }
- }
- virtual FindResult findZone(const Name& name) const {
- if (zones.empty()) {
- return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
- }
- set<Name>::const_iterator it(zones.upper_bound(name));
- if (it == zones.begin()) {
- return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
- }
- --it;
- NameComparisonResult compar(it->compare(name));
- const ZoneFinderPtr finder(new Finder(*it));
- switch (compar.getRelation()) {
- case NameComparisonResult::EQUAL:
- return (FindResult(result::SUCCESS, finder));
- case NameComparisonResult::SUPERDOMAIN:
- return (FindResult(result::PARTIALMATCH, finder));
- default:
- return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
- }
- }
- // These methods are not used. They just need to be there to have
- // complete vtable.
- virtual ZoneUpdaterPtr getUpdater(const Name&, bool, bool) const {
- isc_throw(isc::NotImplemented, "Not implemented");
- }
- virtual pair<ZoneJournalReader::Result, ZoneJournalReaderPtr>
- getJournalReader(const Name&, uint32_t, uint32_t) const
- {
- isc_throw(isc::NotImplemented, "Not implemented");
- }
- virtual ZoneIteratorPtr getIterator(const Name& name, bool) const {
- if (use_baditerator_ && name == Name("noiter.org")) {
- isc_throw(isc::NotImplemented, "Asked not to be implemented");
- } else if (use_baditerator_ && name == Name("null.org")) {
- return (ZoneIteratorPtr());
- } else {
- FindResult result(findZone(name));
- if (result.code == isc::datasrc::result::SUCCESS) {
- return (ZoneIteratorPtr(new Iterator(name, have_a_)));
- } else {
- isc_throw(DataSourceError, "No such zone");
- }
- }
- }
- void disableA() { have_a_ = false; }
- void disableBadIterator() { use_baditerator_ = false; }
- const string type_;
- const ConstElementPtr configuration_;
- private:
- set<Name> zones;
- bool have_a_; // control the iterator behavior whether to include A record
- bool use_baditerator_; // whether to use bogus zone iterators for tests
- };
- // The test version is the same as the normal version. We, however, add
- // some methods to dig directly in the internals, for the tests.
- class TestedList : public ConfigurableClientList {
- public:
- TestedList(const RRClass& rrclass) :
- ConfigurableClientList(rrclass)
- {}
- DataSources& getDataSources() { return (data_sources_); }
- // Overwrite the list's method to get a data source with given type
- // and configuration. We mock the data source and don't create the
- // container. This is just to avoid some complexity in the tests.
- virtual DataSourcePair getDataSourceClient(const string& type,
- const ConstElementPtr&
- configuration)
- {
- if (type == "error") {
- isc_throw(DataSourceError, "The error data source type");
- }
- shared_ptr<MockDataSourceClient>
- ds(new MockDataSourceClient(type, configuration));
- // Make sure it is deleted when the test list is deleted.
- to_delete_.push_back(ds);
- return (DataSourcePair(ds.get(), DataSourceClientContainerPtr()));
- }
- private:
- // Hold list of data sources created internally, so they are preserved
- // until the end of the test and then deleted.
- vector<shared_ptr<MockDataSourceClient> > to_delete_;
- };
- const char* ds_zones[][3] = {
- {
- "example.org.",
- "example.com.",
- NULL
- },
- {
- "sub.example.org.",
- NULL, NULL
- },
- {
- NULL, NULL, NULL
- },
- {
- "sub.example.org.",
- NULL, NULL
- }
- };
- const size_t ds_count = (sizeof(ds_zones) / sizeof(*ds_zones));
- class ListTest : public ::testing::Test {
- public:
- ListTest() :
- rrclass_(RRClass::IN()),
- // The empty list corresponds to a list with no elements inside
- list_(new TestedList(rrclass_)),
- config_elem_(Element::fromJSON("["
- "{"
- " \"type\": \"test_type\","
- " \"params\": {}"
- "}]")),
- config_elem_zones_(Element::fromJSON("["
- "{"
- " \"type\": \"test_type\","
- " \"params\": [\"example.org\", \"example.com\", "
- " \"noiter.org\", \"null.org\"]"
- "}]")),
- config_(Element::fromJSON("{}")),
- ztable_segment_(ZoneTableSegment::create(*config_, rrclass_))
- {
- for (size_t i(0); i < ds_count; ++ i) {
- shared_ptr<MockDataSourceClient>
- ds(new MockDataSourceClient(ds_zones[i]));
- ds_.push_back(ds);
- ds_info_.push_back(ConfigurableClientList::DataSourceInfo(
- ds.get(), DataSourceClientContainerPtr(),
- false, rrclass_, ztable_segment_, ""));
- }
- }
- // Install a "fake" cached zone using a temporary underlying data source
- // client.
- void prepareCache(size_t index, const Name& zone) {
- // Prepare the temporary data source client
- const char* zones[2];
- const std::string zonename_txt = zone.toText();
- zones[0] = zonename_txt.c_str();
- zones[1] = NULL;
- MockDataSourceClient mock_client(zones);
- // Disable some default features of the mock to distinguish the
- // temporary case from normal case.
- mock_client.disableA();
- mock_client.disableBadIterator();
- // Create cache from the temporary data source, and push it to the
- // client list.
- const shared_ptr<InMemoryClient> cache(
- new InMemoryClient(ztable_segment_, rrclass_));
- cache->load(zone, *mock_client.getIterator(zone, false));
- ConfigurableClientList::DataSourceInfo& dsrc_info =
- list_->getDataSources()[index];
- dsrc_info.cache_ = cache;
- dsrc_info.ztable_segment_ = ztable_segment_;
- }
- // Check the positive result is as we expect it.
- void positiveResult(const ClientList::FindResult& result,
- const shared_ptr<MockDataSourceClient>& dsrc,
- const Name& name, bool exact,
- const char* test, bool from_cache = false)
- {
- SCOPED_TRACE(test);
- ASSERT_NE(ZoneFinderPtr(), result.finder_);
- EXPECT_EQ(name, result.finder_->getOrigin());
- EXPECT_EQ(exact, result.exact_match_);
- // If it is a positive result, there's something to keep
- // alive, even when we don't know what it is.
- // Any better idea how to test it actually keeps the thing
- // alive?
- EXPECT_NE(shared_ptr<ClientList::FindResult::LifeKeeper>(),
- result.life_keeper_);
- if (from_cache) {
- EXPECT_NE(shared_ptr<InMemoryZoneFinder>(),
- boost::dynamic_pointer_cast<InMemoryZoneFinder>(
- result.finder_)) << "Finder is not from cache";
- EXPECT_TRUE(NULL !=
- dynamic_cast<InMemoryClient*>(result.dsrc_client_));
- } else {
- EXPECT_EQ(dsrc.get(), result.dsrc_client_);
- }
- }
- // Configure the list with multiple data sources, according to
- // some configuration. It uses the index as parameter, to be able to
- // loop through the configurations.
- void multiConfiguration(size_t index) {
- list_->getDataSources().clear();
- switch (index) {
- case 2:
- list_->getDataSources().push_back(ds_info_[2]);
- // The ds_[2] is empty. We just check that it doesn't confuse
- // us. Fall through to the case 0.
- case 0:
- list_->getDataSources().push_back(ds_info_[0]);
- list_->getDataSources().push_back(ds_info_[1]);
- break;
- case 1:
- // The other order
- list_->getDataSources().push_back(ds_info_[1]);
- list_->getDataSources().push_back(ds_info_[0]);
- break;
- case 3:
- list_->getDataSources().push_back(ds_info_[1]);
- list_->getDataSources().push_back(ds_info_[0]);
- // It is the same as ds_[1], but we take from the first one.
- // The first one to match is the correct one.
- list_->getDataSources().push_back(ds_info_[3]);
- break;
- default:
- FAIL() << "Unknown configuration index " << index;
- }
- }
- void checkDS(size_t index, const string& type, const string& params,
- bool cache) const
- {
- ASSERT_GT(list_->getDataSources().size(), index);
- MockDataSourceClient* ds(dynamic_cast<MockDataSourceClient*>(
- list_->getDataSources()[index].data_src_client_));
- // Comparing with NULL does not work
- ASSERT_NE(ds, static_cast<const MockDataSourceClient*>(NULL));
- EXPECT_EQ(type, ds->type_);
- EXPECT_TRUE(Element::fromJSON(params)->equals(*ds->configuration_));
- EXPECT_EQ(cache, list_->getDataSources()[index].cache_ !=
- shared_ptr<InMemoryClient>());
- }
- const RRClass rrclass_;
- shared_ptr<TestedList> list_;
- const ClientList::FindResult negative_result_;
- vector<shared_ptr<MockDataSourceClient> > ds_;
- vector<ConfigurableClientList::DataSourceInfo> ds_info_;
- const ConstElementPtr config_elem_, config_elem_zones_, config_;
- shared_ptr<ZoneTableSegment> ztable_segment_;
- };
- // Test the test itself
- TEST_F(ListTest, selfTest) {
- EXPECT_EQ(result::SUCCESS, ds_[0]->findZone(Name("example.org")).code);
- EXPECT_EQ(result::PARTIALMATCH,
- ds_[0]->findZone(Name("sub.example.org")).code);
- EXPECT_EQ(result::NOTFOUND, ds_[0]->findZone(Name("org")).code);
- EXPECT_EQ(result::NOTFOUND, ds_[1]->findZone(Name("example.org")).code);
- EXPECT_EQ(result::NOTFOUND, ds_[0]->findZone(Name("aaa")).code);
- EXPECT_EQ(result::NOTFOUND, ds_[0]->findZone(Name("zzz")).code);
- // Nothing to keep alive here.
- EXPECT_EQ(shared_ptr<ClientList::FindResult::LifeKeeper>(),
- negative_result_.life_keeper_);
- }
- // Test the list we create with empty configuration is, in fact, empty
- TEST_F(ListTest, emptyList) {
- EXPECT_TRUE(list_->getDataSources().empty());
- }
- // Check the values returned by a find on an empty list. It should be
- // a negative answer (nothing found) no matter if we want an exact or inexact
- // match.
- TEST_F(ListTest, emptySearch) {
- // No matter what we try, we don't get an answer.
- // Note: we don't have operator<< for the result class, so we cannot use
- // EXPECT_EQ. Same for other similar cases.
- EXPECT_TRUE(negative_result_ == list_->find(Name("example.org"), false,
- false));
- EXPECT_TRUE(negative_result_ == list_->find(Name("example.org"), false,
- true));
- EXPECT_TRUE(negative_result_ == list_->find(Name("example.org"), true,
- false));
- EXPECT_TRUE(negative_result_ == list_->find(Name("example.org"), true,
- true));
- }
- // Put a single data source inside the list and check it can find an
- // exact match if there's one.
- TEST_F(ListTest, singleDSExactMatch) {
- list_->getDataSources().push_back(ds_info_[0]);
- // This zone is not there
- EXPECT_TRUE(negative_result_ == list_->find(Name("org."), true));
- // But this one is, so check it.
- positiveResult(list_->find(Name("example.org"), true), ds_[0],
- Name("example.org"), true, "Exact match");
- // When asking for a sub zone of a zone there, we get nothing
- // (we want exact match, this would be partial one)
- EXPECT_TRUE(negative_result_ == list_->find(Name("sub.example.org."),
- true));
- }
- // When asking for a partial match, we get all that the exact one, but more.
- TEST_F(ListTest, singleDSBestMatch) {
- list_->getDataSources().push_back(ds_info_[0]);
- // This zone is not there
- EXPECT_TRUE(negative_result_ == list_->find(Name("org.")));
- // But this one is, so check it.
- positiveResult(list_->find(Name("example.org")), ds_[0],
- Name("example.org"), true, "Exact match");
- // When asking for a sub zone of a zone there, we get the parent
- // one.
- positiveResult(list_->find(Name("sub.example.org.")), ds_[0],
- Name("example.org"), false, "Subdomain match");
- }
- const char* const test_names[] = {
- "Sub second",
- "Sub first",
- "With empty",
- "With a duplicity"
- };
- TEST_F(ListTest, multiExactMatch) {
- // Run through all the multi-configurations
- for (size_t i(0); i < sizeof(test_names) / sizeof(*test_names); ++i) {
- SCOPED_TRACE(test_names[i]);
- multiConfiguration(i);
- // Something that is nowhere there
- EXPECT_TRUE(negative_result_ == list_->find(Name("org."), true));
- // This one is there exactly.
- positiveResult(list_->find(Name("example.org"), true), ds_[0],
- Name("example.org"), true, "Exact match");
- // This one too, but in a different data source.
- positiveResult(list_->find(Name("sub.example.org."), true), ds_[1],
- Name("sub.example.org"), true, "Subdomain match");
- // But this one is in neither data source.
- EXPECT_TRUE(negative_result_ ==
- list_->find(Name("sub.example.com."), true));
- }
- }
- TEST_F(ListTest, multiBestMatch) {
- // Run through all the multi-configurations
- for (size_t i(0); i < 4; ++ i) {
- SCOPED_TRACE(test_names[i]);
- multiConfiguration(i);
- // Something that is nowhere there
- EXPECT_TRUE(negative_result_ == list_->find(Name("org.")));
- // This one is there exactly.
- positiveResult(list_->find(Name("example.org")), ds_[0],
- Name("example.org"), true, "Exact match");
- // This one too, but in a different data source.
- positiveResult(list_->find(Name("sub.example.org.")), ds_[1],
- Name("sub.example.org"), true, "Subdomain match");
- // But this one is in neither data source. But it is a subdomain
- // of one of the zones in the first data source.
- positiveResult(list_->find(Name("sub.example.com.")), ds_[0],
- Name("example.com."), false, "Subdomain in com");
- }
- }
- // Check the configuration is empty when the list is empty
- TEST_F(ListTest, configureEmpty) {
- const ConstElementPtr elem(new ListElement);
- list_->configure(elem, true);
- EXPECT_TRUE(list_->getDataSources().empty());
- // Check the exact configuration is preserved
- EXPECT_EQ(elem, list_->getConfiguration());
- }
- // Check we can get multiple data sources and they are in the right order.
- TEST_F(ListTest, configureMulti) {
- const ConstElementPtr elem(Element::fromJSON("["
- "{"
- " \"type\": \"type1\","
- " \"cache-enable\": false,"
- " \"params\": {}"
- "},"
- "{"
- " \"type\": \"type2\","
- " \"cache-enable\": false,"
- " \"params\": {}"
- "}]"
- ));
- list_->configure(elem, true);
- EXPECT_EQ(2, list_->getDataSources().size());
- checkDS(0, "type1", "{}", false);
- checkDS(1, "type2", "{}", false);
- // Check the exact configuration is preserved
- EXPECT_EQ(elem, list_->getConfiguration());
- }
- // Check we can pass whatever we want to the params
- TEST_F(ListTest, configureParams) {
- const char* params[] = {
- "true",
- "false",
- "null",
- "\"hello\"",
- "42",
- "[]",
- "{}",
- NULL
- };
- for (const char** param(params); *param; ++param) {
- SCOPED_TRACE(*param);
- ConstElementPtr elem(Element::fromJSON(string("["
- "{"
- " \"type\": \"t\","
- " \"cache-enable\": false,"
- " \"params\": ") + *param +
- "}]"));
- list_->configure(elem, true);
- EXPECT_EQ(1, list_->getDataSources().size());
- checkDS(0, "t", *param, false);
- }
- }
- TEST_F(ListTest, status) {
- EXPECT_TRUE(list_->getStatus().empty());
- const ConstElementPtr elem(Element::fromJSON("["
- "{"
- " \"type\": \"type1\","
- " \"cache-enable\": false,"
- " \"params\": {}"
- "},"
- "{"
- " \"type\": \"type2\","
- " \"cache-enable\": true,"
- " \"cache-zones\": [],"
- " \"name\": \"Test name\","
- " \"params\": {}"
- "}]"
- ));
- list_->configure(elem, true);
- const vector<DataSourceStatus> statuses(list_->getStatus());
- ASSERT_EQ(2, statuses.size());
- EXPECT_EQ("type1", statuses[0].getName());
- EXPECT_EQ(SEGMENT_UNUSED, statuses[0].getSegmentState());
- EXPECT_THROW(statuses[0].getSegmentType(), isc::BadValue);
- EXPECT_EQ("Test name", statuses[1].getName());
- EXPECT_EQ(SEGMENT_INUSE, statuses[1].getSegmentState());
- EXPECT_EQ(SEGMENT_LOCAL, statuses[1].getSegmentType());
- }
- TEST_F(ListTest, wrongConfig) {
- const char* configs[] = {
- // A lot of stuff missing from there
- "[{\"type\": \"test_type\", \"params\": 13}, {}]",
- // Some bad types completely
- "{}",
- "true",
- "42",
- "null",
- "[{\"type\": \"test_type\", \"params\": 13}, true]",
- "[{\"type\": \"test_type\", \"params\": 13}, []]",
- "[{\"type\": \"test_type\", \"params\": 13}, 42]",
- // Bad type of type
- "[{\"type\": \"test_type\", \"params\": 13}, {\"type\": 42}]",
- "[{\"type\": \"test_type\", \"params\": 13}, {\"type\": true}]",
- "[{\"type\": \"test_type\", \"params\": 13}, {\"type\": null}]",
- "[{\"type\": \"test_type\", \"params\": 13}, {\"type\": []}]",
- "[{\"type\": \"test_type\", \"params\": 13}, {\"type\": {}}]",
- // Bad type of cache-enable
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"x\", \"cache-enable\": 13, \"cache-zones\": []}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"x\", \"cache-enable\": \"xx\", \"cache-zones\": []}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"x\", \"cache-enable\": [], \"cache-zones\": []}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"x\", \"cache-enable\": {}, \"cache-zones\": []}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"x\", \"cache-enable\": null, \"cache-zones\": []}]",
- // Bad type of cache-zones
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"x\", \"cache-enable\": true, \"cache-zones\": \"x\"}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"x\", \"cache-enable\": true, \"cache-zones\": true}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"x\", \"cache-enable\": true, \"cache-zones\": null}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"x\", \"cache-enable\": true, \"cache-zones\": 13}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"x\", \"cache-enable\": true, \"cache-zones\": {}}]",
- // Some bad inputs for MasterFiles special case
- // It must have the cache enabled
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": {}}]",
- // No cache-zones allowed here
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": true,"
- "\"param\": {}, \"cache-zones\": []}]",
- // Some bad types of params
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": []}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": 13}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": true}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": null}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": \"x\"}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": {\".\": 13}}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": {\".\": true}}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": {\".\": null}}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": {\".\": []}}]",
- "[{\"type\": \"test_type\", \"params\": 13}, "
- "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
- "\"params\": {\".\": {}}}]",
- NULL
- };
- // Put something inside to see it survives the exception
- list_->configure(config_elem_, true);
- checkDS(0, "test_type", "{}", false);
- for (const char** config(configs); *config; ++config) {
- SCOPED_TRACE(*config);
- ConstElementPtr elem(Element::fromJSON(*config));
- EXPECT_THROW(list_->configure(elem, true),
- ConfigurableClientList::ConfigurationError);
- // Still untouched
- checkDS(0, "test_type", "{}", false);
- EXPECT_EQ(1, list_->getDataSources().size());
- }
- }
- // The param thing defaults to null. Cache is not used yet.
- TEST_F(ListTest, defaults) {
- const ConstElementPtr elem(Element::fromJSON("["
- "{"
- " \"type\": \"type1\""
- "}]"));
- list_->configure(elem, true);
- EXPECT_EQ(1, list_->getDataSources().size());
- checkDS(0, "type1", "null", false);
- }
- // Check we can call the configure multiple times, to change the configuration
- TEST_F(ListTest, reconfigure) {
- const ConstElementPtr empty(new ListElement);
- list_->configure(config_elem_, true);
- checkDS(0, "test_type", "{}", false);
- list_->configure(empty, true);
- EXPECT_TRUE(list_->getDataSources().empty());
- list_->configure(config_elem_, true);
- checkDS(0, "test_type", "{}", false);
- }
- // Make sure the data source error exception from the factory is propagated
- TEST_F(ListTest, dataSrcError) {
- const ConstElementPtr elem(Element::fromJSON("["
- "{"
- " \"type\": \"error\""
- "}]"));
- list_->configure(config_elem_, true);
- checkDS(0, "test_type", "{}", false);
- EXPECT_THROW(list_->configure(elem, true), DataSourceError);
- checkDS(0, "test_type", "{}", false);
- }
- // Check we can get the cache
- TEST_F(ListTest, configureCacheEmpty) {
- const ConstElementPtr elem(Element::fromJSON("["
- "{"
- " \"type\": \"type1\","
- " \"cache-enable\": true,"
- " \"cache-zones\": [],"
- " \"params\": {}"
- "},"
- "{"
- " \"type\": \"type2\","
- " \"cache-enable\": false,"
- " \"cache-zones\": [],"
- " \"params\": {}"
- "}]"
- ));
- list_->configure(elem, true);
- EXPECT_EQ(2, list_->getDataSources().size());
- checkDS(0, "type1", "{}", true);
- checkDS(1, "type2", "{}", false);
- }
- // But no cache if we disallow it globally
- TEST_F(ListTest, configureCacheDisabled) {
- const ConstElementPtr elem(Element::fromJSON("["
- "{"
- " \"type\": \"type1\","
- " \"cache-enable\": true,"
- " \"cache-zones\": [],"
- " \"params\": {}"
- "},"
- "{"
- " \"type\": \"type2\","
- " \"cache-enable\": false,"
- " \"cache-zones\": [],"
- " \"params\": {}"
- "}]"
- ));
- list_->configure(elem, false);
- EXPECT_EQ(2, list_->getDataSources().size());
- checkDS(0, "type1", "{}", false);
- checkDS(1, "type2", "{}", false);
- }
- // Put some zones into the cache
- TEST_F(ListTest, cacheZones) {
- const ConstElementPtr elem(Element::fromJSON("["
- "{"
- " \"type\": \"type1\","
- " \"cache-enable\": true,"
- " \"cache-zones\": [\"example.org\", \"example.com\"],"
- " \"params\": [\"example.org\", \"example.com\", \"exmaple.cz\"]"
- "}]"));
- list_->configure(elem, true);
- checkDS(0, "type1", "[\"example.org\", \"example.com\", \"exmaple.cz\"]",
- true);
- const shared_ptr<InMemoryClient> cache(list_->getDataSources()[0].cache_);
- EXPECT_EQ(2, cache->getZoneCount());
- EXPECT_EQ(result::SUCCESS, cache->findZone(Name("example.org")).code);
- EXPECT_EQ(result::SUCCESS, cache->findZone(Name("example.com")).code);
- EXPECT_EQ(result::NOTFOUND, cache->findZone(Name("example.cz")).code);
- EXPECT_EQ(RRClass::IN(),
- cache->findZone(Name("example.org")).zone_finder->getClass());
- // These are cached and answered from the cache
- positiveResult(list_->find(Name("example.com.")), ds_[0],
- Name("example.com."), true, "com", true);
- positiveResult(list_->find(Name("example.org.")), ds_[0],
- Name("example.org."), true, "org", true);
- positiveResult(list_->find(Name("sub.example.com.")), ds_[0],
- Name("example.com."), false, "Subdomain of com", true);
- // For now, the ones not cached are ignored.
- EXPECT_TRUE(negative_result_ == list_->find(Name("example.cz.")));
- }
- // Check the caching handles misbehaviour from the data source and
- // misconfiguration gracefully
- TEST_F(ListTest, badCache) {
- list_->configure(config_elem_, true);
- checkDS(0, "test_type", "{}", false);
- // First, the zone is not in the data source
- const ConstElementPtr elem1(Element::fromJSON("["
- "{"
- " \"type\": \"type1\","
- " \"cache-enable\": true,"
- " \"cache-zones\": [\"example.org\"],"
- " \"params\": []"
- "}]"));
- EXPECT_THROW(list_->configure(elem1, true),
- ConfigurableClientList::ConfigurationError);
- checkDS(0, "test_type", "{}", false);
- // Now, the zone doesn't give an iterator
- const ConstElementPtr elem2(Element::fromJSON("["
- "{"
- " \"type\": \"type1\","
- " \"cache-enable\": true,"
- " \"cache-zones\": [\"noiter.org\"],"
- " \"params\": [\"noiter.org\"]"
- "}]"));
- EXPECT_THROW(list_->configure(elem2, true), isc::NotImplemented);
- checkDS(0, "test_type", "{}", false);
- // Now, the zone returns NULL iterator
- const ConstElementPtr elem3(Element::fromJSON("["
- "{"
- " \"type\": \"type1\","
- " \"cache-enable\": true,"
- " \"cache-zones\": [\"null.org\"],"
- " \"params\": [\"null.org\"]"
- "}]"));
- EXPECT_THROW(list_->configure(elem3, true), isc::Unexpected);
- checkDS(0, "test_type", "{}", false);
- // The autodetection of zones is not enabled
- const ConstElementPtr elem4(Element::fromJSON("["
- "{"
- " \"type\": \"type1\","
- " \"cache-enable\": true,"
- " \"params\": [\"example.org\"]"
- "}]"));
- EXPECT_THROW(list_->configure(elem4, true), isc::NotImplemented);
- checkDS(0, "test_type", "{}", false);
- }
- TEST_F(ListTest, masterFiles) {
- const ConstElementPtr elem(Element::fromJSON("["
- "{"
- " \"type\": \"MasterFiles\","
- " \"cache-enable\": true,"
- " \"params\": {"
- " \".\": \"" TEST_DATA_DIR "/root.zone\""
- " }"
- "}]"));
- list_->configure(elem, true);
- // It has only the cache
- EXPECT_EQ(static_cast<const DataSourceClient*>(NULL),
- list_->getDataSources()[0].data_src_client_);
- // And it can search
- positiveResult(list_->find(Name(".")), ds_[0], Name("."), true, "com",
- true);
- // If cache is not enabled, nothing is loaded
- list_->configure(elem, false);
- EXPECT_EQ(0, list_->getDataSources().size());
- }
- // Test the names are set correctly and collission is detected.
- TEST_F(ListTest, names) {
- // Explicit name
- const ConstElementPtr elem1(Element::fromJSON("["
- "{"
- " \"type\": \"MasterFiles\","
- " \"cache-enable\": true,"
- " \"params\": {"
- " \".\": \"" TEST_DATA_DIR "/root.zone\""
- " },"
- " \"name\": \"Whatever\""
- "}]"));
- list_->configure(elem1, true);
- EXPECT_EQ("Whatever", list_->getDataSources()[0].name_);
- // Default name
- const ConstElementPtr elem2(Element::fromJSON("["
- "{"
- " \"type\": \"MasterFiles\","
- " \"cache-enable\": true,"
- " \"params\": {"
- " \".\": \"" TEST_DATA_DIR "/root.zone\""
- " }"
- "}]"));
- list_->configure(elem2, true);
- EXPECT_EQ("MasterFiles", list_->getDataSources()[0].name_);
- // Collission
- const ConstElementPtr elem3(Element::fromJSON("["
- "{"
- " \"type\": \"MasterFiles\","
- " \"cache-enable\": true,"
- " \"params\": {"
- " \".\": \"" TEST_DATA_DIR "/root.zone\""
- " }"
- "},"
- "{"
- " \"type\": \"MasterFiles\","
- " \"cache-enable\": true,"
- " \"params\": {"
- " \".\": \"" TEST_DATA_DIR "/root.zone\""
- " },"
- " \"name\": \"MasterFiles\""
- "}]"));
- EXPECT_THROW(list_->configure(elem3, true),
- ConfigurableClientList::ConfigurationError);
- }
- TEST_F(ListTest, BadMasterFile) {
- // Configuration should succeed, and the good zones in the list
- // below should be loaded. No bad zones should be loaded.
- const ConstElementPtr elem(Element::fromJSON("["
- "{"
- " \"type\": \"MasterFiles\","
- " \"cache-enable\": true,"
- " \"params\": {"
- // good zone
- " \"example.com.\": \"" TEST_DATA_DIR "/example.com.flattened\","
- // bad zone (empty file)
- " \"example.net.\": \"" TEST_DATA_DIR "/example.net-empty\","
- // bad zone (data doesn't validate: see the file for details)
- " \"example.edu.\": \"" TEST_DATA_DIR "/example.edu-broken\","
- // bad zone (file doesn't exist)
- " \"example.info.\": \"" TEST_DATA_DIR "/example.info-nonexist\","
- // bad zone (data doesn't match the zone name)
- " \"foo.bar.\": \"" TEST_DATA_DIR "/example.org.nsec3-signed\","
- // good zone
- " \".\": \"" TEST_DATA_DIR "/root.zone\""
- " }"
- "}]"));
- EXPECT_NO_THROW({
- // This should not throw even if there are any zone loading
- // errors.
- list_->configure(elem, true);
- });
- positiveResult(list_->find(Name("example.com."), true), ds_[0],
- Name("example.com."), true, "example.com", true);
- EXPECT_TRUE(negative_result_ == list_->find(Name("example.org."), true));
- EXPECT_TRUE(negative_result_ == list_->find(Name("foo.bar"), true));
- EXPECT_TRUE(negative_result_ == list_->find(Name("example.net."), true));
- EXPECT_TRUE(negative_result_ == list_->find(Name("example.edu."), true));
- EXPECT_TRUE(negative_result_ == list_->find(Name("example.info."), true));
- positiveResult(list_->find(Name(".")), ds_[0], Name("."), true, "root",
- true);
- }
- // This allows us to test two versions of the reloading code
- // (One by calling reload(), one by obtaining a ZoneWriter and
- // playing with that). Once we deprecate reload(), we should revert this
- // change and not use typed tests any more.
- template<class UpdateType>
- class ReloadTest : public ListTest {
- public:
- ConfigurableClientList::ReloadResult doReload(const Name& origin);
- };
- // Version with calling reload()
- class ReloadUpdateType {};
- template<>
- ConfigurableClientList::ReloadResult
- ReloadTest<ReloadUpdateType>::doReload(const Name& origin) {
- return (list_->reload(origin));
- };
- // Version with the ZoneWriter
- class WriterUpdateType {};
- template<>
- ConfigurableClientList::ReloadResult
- ReloadTest<WriterUpdateType>::doReload(const Name& origin) {
- ConfigurableClientList::ZoneWriterPair
- result(list_->getCachedZoneWriter(origin));
- if (result.first == ConfigurableClientList::ZONE_SUCCESS) {
- // Can't use ASSERT_NE here, it would want to return(), which
- // it can't in non-void function.
- if (result.second) {
- result.second->load();
- result.second->install();
- result.second->cleanup();
- } else {
- ADD_FAILURE() << "getCachedZoneWriter returned ZONE_SUCCESS, "
- "but the writer is NULL";
- }
- } else {
- EXPECT_EQ(static_cast<memory::ZoneWriter*>(NULL),
- result.second.get());
- }
- return (result.first);
- }
- // Typedefs for the GTEST guts to make it work
- typedef ::testing::Types<ReloadUpdateType, WriterUpdateType> UpdateTypes;
- TYPED_TEST_CASE(ReloadTest, UpdateTypes);
- // Test we can reload a zone
- TYPED_TEST(ReloadTest, reloadSuccess) {
- this->list_->configure(this->config_elem_zones_, true);
- const Name name("example.org");
- this->prepareCache(0, name);
- // The cache currently contains a tweaked version of zone, which
- // doesn't have "tstzonedata" A record. So the lookup should result
- // in NXDOMAIN.
- EXPECT_EQ(ZoneFinder::NXDOMAIN,
- this->list_->find(name).finder_->
- find(Name("tstzonedata").concatenate(name),
- RRType::A())->code);
- // Now reload the full zone. It should be there now.
- EXPECT_EQ(ConfigurableClientList::ZONE_SUCCESS, this->doReload(name));
- EXPECT_EQ(ZoneFinder::SUCCESS,
- this->list_->find(name).finder_->
- find(Name("tstzonedata").concatenate(name),
- RRType::A())->code);
- }
- // The cache is not enabled. The load should be rejected.
- TYPED_TEST(ReloadTest, reloadNotEnabled) {
- this->list_->configure(this->config_elem_zones_, false);
- const Name name("example.org");
- // We put the cache in even when not enabled. This won't confuse the thing.
- this->prepareCache(0, name);
- // See the reloadSuccess test. This should result in NXDOMAIN.
- EXPECT_EQ(ZoneFinder::NXDOMAIN,
- this->list_->find(name).finder_->
- find(Name("tstzonedata").concatenate(name),
- RRType::A())->code);
- // Now reload. It should reject it.
- EXPECT_EQ(ConfigurableClientList::CACHE_DISABLED, this->doReload(name));
- // Nothing changed here
- EXPECT_EQ(ZoneFinder::NXDOMAIN,
- this->list_->find(name).finder_->
- find(Name("tstzonedata").concatenate(name),
- RRType::A())->code);
- }
- // Test several cases when the zone does not exist
- TYPED_TEST(ReloadTest, reloadNoSuchZone) {
- this->list_->configure(this->config_elem_zones_, true);
- const Name name("example.org");
- // We put the cache in even when not enabled. This won't confuse the
- // reload method, as that one looks at the real state of things, not
- // at the configuration.
- this->prepareCache(0, Name("example.com"));
- // Not in the data sources
- EXPECT_EQ(ConfigurableClientList::ZONE_NOT_FOUND,
- this->doReload(Name("exmaple.cz")));
- // Not cached
- EXPECT_EQ(ConfigurableClientList::ZONE_NOT_FOUND, this->doReload(name));
- // Partial match
- EXPECT_EQ(ConfigurableClientList::ZONE_NOT_FOUND,
- this->doReload(Name("sub.example.com")));
- // Nothing changed here - these zones don't exist
- EXPECT_EQ(static_cast<isc::datasrc::DataSourceClient*>(NULL),
- this->list_->find(name).dsrc_client_);
- EXPECT_EQ(static_cast<isc::datasrc::DataSourceClient*>(NULL),
- this->list_->find(Name("example.cz")).dsrc_client_);
- EXPECT_EQ(static_cast<isc::datasrc::DataSourceClient*>(NULL),
- this->list_->find(Name("sub.example.com"), true).dsrc_client_);
- // Not reloaded, so A record shouldn't be visible yet.
- EXPECT_EQ(ZoneFinder::NXDOMAIN,
- this->list_->find(Name("example.com")).finder_->
- find(Name("tstzonedata.example.com"),
- RRType::A())->code);
- }
- // Check we gracefuly throw an exception when a zone disappeared in
- // the underlying data source when we want to reload it
- TYPED_TEST(ReloadTest, reloadZoneGone) {
- this->list_->configure(this->config_elem_, true);
- const Name name("example.org");
- // We put in a cache for non-existent zone. This emulates being loaded
- // and then the zone disappearing. We prefill the cache, so we can check
- // it.
- this->prepareCache(0, name);
- // The (cached) zone contains zone's SOA
- EXPECT_EQ(ZoneFinder::SUCCESS,
- this->list_->find(name).finder_->find(name,
- RRType::SOA())->code);
- // The zone is not there, so abort the reload.
- EXPECT_THROW(this->doReload(name), DataSourceError);
- // The (cached) zone is not hurt.
- EXPECT_EQ(ZoneFinder::SUCCESS,
- this->list_->find(name).finder_->find(name,
- RRType::SOA())->code);
- }
- // The underlying data source throws. Check we don't modify the state.
- TYPED_TEST(ReloadTest, reloadZoneThrow) {
- this->list_->configure(this->config_elem_zones_, true);
- const Name name("noiter.org");
- this->prepareCache(0, name);
- // The zone contains stuff now
- EXPECT_EQ(ZoneFinder::SUCCESS,
- this->list_->find(name).finder_->find(name,
- RRType::SOA())->code);
- // The iterator throws, so abort the reload.
- EXPECT_THROW(this->doReload(name), isc::NotImplemented);
- // The zone is not hurt.
- EXPECT_EQ(ZoneFinder::SUCCESS,
- this->list_->find(name).finder_->find(name,
- RRType::SOA())->code);
- }
- TYPED_TEST(ReloadTest, reloadNullIterator) {
- this->list_->configure(this->config_elem_zones_, true);
- const Name name("null.org");
- this->prepareCache(0, name);
- // The zone contains stuff now
- EXPECT_EQ(ZoneFinder::SUCCESS,
- this->list_->find(name).finder_->find(name,
- RRType::SOA())->code);
- // The iterator throws, so abort the reload.
- EXPECT_THROW(this->doReload(name), isc::Unexpected);
- // The zone is not hurt.
- EXPECT_EQ(ZoneFinder::SUCCESS,
- this->list_->find(name).finder_->find(name,
- RRType::SOA())->code);
- }
- // Test we can reload the master files too (special-cased)
- TYPED_TEST(ReloadTest, reloadMasterFile) {
- const char* const install_cmd = INSTALL_PROG " -c " TEST_DATA_DIR
- "/root.zone " TEST_DATA_BUILDDIR "/root.zone.copied";
- if (system(install_cmd) != 0) {
- // any exception will do, this is failure in test setup, but
- // nice to show the command that fails, and shouldn't be caught
- isc_throw(isc::Exception,
- "Error setting up; command failed: " << install_cmd);
- }
- const ConstElementPtr elem(Element::fromJSON("["
- "{"
- " \"type\": \"MasterFiles\","
- " \"cache-enable\": true,"
- " \"params\": {"
- " \".\": \"" TEST_DATA_BUILDDIR "/root.zone.copied\""
- " }"
- "}]"));
- this->list_->configure(elem, true);
- // Add a record that is not in the zone
- EXPECT_EQ(ZoneFinder::NXDOMAIN,
- this->list_->find(Name(".")).finder_->find(Name("nosuchdomain"),
- RRType::TXT())->code);
- ofstream f;
- f.open(TEST_DATA_BUILDDIR "/root.zone.copied", ios::out | ios::app);
- f << "nosuchdomain.\t\t3600\tIN\tTXT\ttest" << std::endl;
- f.close();
- // Do the reload.
- EXPECT_EQ(ConfigurableClientList::ZONE_SUCCESS, this->doReload(Name(".")));
- // It is here now.
- EXPECT_EQ(ZoneFinder::SUCCESS,
- this->list_->find(Name(".")).finder_->find(Name("nosuchdomain"),
- RRType::TXT())->code);
- }
- // Check the status holds data and can change the segment state
- TEST(DataSourceStatus, status) {
- const DataSourceStatus status("Test", SEGMENT_INUSE, SEGMENT_LOCAL);
- EXPECT_EQ("Test", status.getName());
- EXPECT_EQ(SEGMENT_INUSE, status.getSegmentState());
- EXPECT_EQ(SEGMENT_LOCAL, status.getSegmentType());
- const DataSourceStatus statusUnused("Unused", SEGMENT_UNUSED, SEGMENT_FILE);
- EXPECT_EQ("Unused", statusUnused.getName());
- EXPECT_EQ(SEGMENT_UNUSED, statusUnused.getSegmentState());
- EXPECT_THROW(statusUnused.getSegmentType(), isc::BadValue);
- }
- }
|