123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- // 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 <auth/datasrc_configurator.h>
- #include <config/tests/fake_session.h>
- #include <config/ccsession.h>
- #include <gtest/gtest.h>
- #include <memory>
- #include <boost/shared_ptr.hpp>
- using namespace isc;
- using namespace isc::cc;
- using namespace isc::config;
- using namespace isc::data;
- using namespace isc::dns;
- using namespace std;
- using namespace boost;
- namespace {
- class DatasrcConfiguratorTest;
- class FakeList {
- public:
- FakeList() :
- configuration_(new ListElement)
- {}
- void configure(const ConstElementPtr& configuration, bool allow_cache) {
- EXPECT_TRUE(allow_cache);
- conf_ = configuration->get(0)->get("type")->stringValue();
- configuration_ = configuration;
- }
- const string& getConf() const {
- return (conf_);
- }
- ConstElementPtr getConfiguration() const {
- return (configuration_);
- }
- private:
- string conf_;
- ConstElementPtr configuration_;
- };
- typedef shared_ptr<FakeList> ListPtr;
- // We use the test fixture as both parameters, this makes it possible
- // to easily fake all needed methods and look that they were called.
- typedef DataSourceConfiguratorGeneric<DatasrcConfiguratorTest,
- FakeList> Configurator;
- class DatasrcConfiguratorTest : public ::testing::Test {
- public:
- // These pretend to be the server
- ListPtr getClientList(const RRClass& rrclass) {
- log_ += "get " + rrclass.toText() + "\n";
- return (lists_[rrclass]);
- }
- void setClientList(const RRClass& rrclass, const ListPtr& list) {
- log_ += "set " + rrclass.toText() + " " +
- (list ? list->getConf() : "") + "\n";
- lists_[rrclass] = list;
- }
- vector<RRClass> getClientListClasses() const {
- vector<RRClass> result;
- for (map<RRClass, ListPtr>::const_iterator it(lists_.begin());
- it != lists_.end(); ++it) {
- result.push_back(it->first);
- }
- return (result);
- }
- protected:
- DatasrcConfiguratorTest() :
- session(ElementPtr(new ListElement), ElementPtr(new ListElement),
- ElementPtr(new ListElement)),
- specfile(string(TEST_OWN_DATA_DIR) + "/spec.spec")
- {
- initSession();
- }
- void initSession() {
- session.getMessages()->add(createAnswer());
- mccs.reset(new ModuleCCSession(specfile, session, NULL, NULL, false,
- false));
- }
- void TearDown() {
- // Make sure no matter what we did, it is cleaned up.
- Configurator::deinit();
- }
- void init(const ElementPtr& config = ElementPtr()) {
- session.getMessages()->
- add(createAnswer(0,
- moduleSpecFromFile(string(PLUGIN_DATA_PATH) +
- "/datasrc.spec").
- getFullSpec()));
- if (config) {
- session.getMessages()->add(createAnswer(0, config));
- } else {
- session.getMessages()->
- add(createAnswer(0, ElementPtr(new MapElement)));
- }
- Configurator::init(mccs.get(), this);
- }
- void SetUp() {
- init();
- }
- void doInInit() {
- const ElementPtr
- config(Element::fromJSON("{\"IN\": [{\"type\": \"xxx\"}]}"));
- session.addMessage(createCommand("config_update", config), "data_sources",
- "*");
- mccs->checkCommand();
- // Check it called the correct things (check that there's no IN yet and
- // set a new one.
- EXPECT_EQ("get IN\nset IN xxx\n", log_);
- }
- FakeSession session;
- auto_ptr<ModuleCCSession> mccs;
- const string specfile;
- map<RRClass, ListPtr> lists_;
- string log_;
- };
- // Check the initialization (and deinitialization)
- TEST_F(DatasrcConfiguratorTest, initialization) {
- // It can't be initialized again
- EXPECT_THROW(init(), InvalidOperation);
- EXPECT_TRUE(session.haveSubscription("data_sources", "*"));
- // Deinitialize to make the tests reasonable
- Configurator::deinit();
- EXPECT_FALSE(session.haveSubscription("data_sources", "*"));
- // We can't reconfigure now (not even manually)
- EXPECT_THROW(Configurator::reconfigure(ElementPtr(new MapElement())),
- InvalidOperation);
- // If one of them is NULL, it does not work
- EXPECT_THROW(Configurator::init(NULL, this), InvalidParameter);
- EXPECT_FALSE(session.haveSubscription("data_sources", "*"));
- EXPECT_THROW(Configurator::init(mccs.get(), NULL), InvalidParameter);
- EXPECT_FALSE(session.haveSubscription("data_sources", "*"));
- // But we can initialize it again now
- EXPECT_NO_THROW(init());
- EXPECT_TRUE(session.haveSubscription("data_sources", "*"));
- }
- // Push there a configuration with a single list.
- TEST_F(DatasrcConfiguratorTest, createList) {
- doInInit();
- }
- TEST_F(DatasrcConfiguratorTest, modifyList) {
- // First, initialize the list
- doInInit();
- // And now change the configuration of the list
- const ElementPtr
- config(Element::fromJSON("{\"IN\": [{\"type\": \"yyy\"}]}"));
- session.addMessage(createCommand("config_update", config), "data_sources",
- "*");
- log_ = "";
- mccs->checkCommand();
- // This one does not set
- EXPECT_EQ("get IN\n", log_);
- // But this should contain the yyy configuration
- EXPECT_EQ("yyy", lists_[RRClass::IN()]->getConf());
- }
- // Check we can have multiple lists at once
- TEST_F(DatasrcConfiguratorTest, multiple) {
- const ElementPtr
- config(Element::fromJSON("{\"IN\": [{\"type\": \"yyy\"}], "
- "\"CH\": [{\"type\": \"xxx\"}]}"));
- session.addMessage(createCommand("config_update", config), "data_sources",
- "*");
- mccs->checkCommand();
- // This one does not set
- EXPECT_EQ("get CH\nset CH xxx\nget IN\nset IN yyy\n", log_);
- // We should have both there
- EXPECT_EQ("yyy", lists_[RRClass::IN()]->getConf());
- EXPECT_EQ("xxx", lists_[RRClass::CH()]->getConf());
- EXPECT_EQ(2, lists_.size());
- }
- // Check we can add another one later and the old one does not get
- // overwritten.
- //
- // It's almost like above, but we initialize first with single-list
- // config.
- TEST_F(DatasrcConfiguratorTest, updateAdd) {
- doInInit();
- const ElementPtr
- config(Element::fromJSON("{\"IN\": [{\"type\": \"yyy\"}], "
- "\"CH\": [{\"type\": \"xxx\"}]}"));
- session.addMessage(createCommand("config_update", config), "data_sources",
- "*");
- log_ = "";
- mccs->checkCommand();
- // This one does not set
- EXPECT_EQ("get CH\nset CH xxx\nget IN\n", log_);
- // But this should contain the yyy configuration
- EXPECT_EQ("xxx", lists_[RRClass::CH()]->getConf());
- EXPECT_EQ("yyy", lists_[RRClass::IN()]->getConf());
- EXPECT_EQ(2, lists_.size());
- }
- // We delete a class list in this test.
- TEST_F(DatasrcConfiguratorTest, updateDelete) {
- doInInit();
- const ElementPtr
- config(Element::fromJSON("{}"));
- session.addMessage(createCommand("config_update", config), "data_sources",
- "*");
- log_ = "";
- mccs->checkCommand();
- EXPECT_EQ("get IN\nset IN \n", log_);
- EXPECT_FALSE(lists_[RRClass::IN()]);
- }
- // Check that we can rollback an addition if something else fails
- TEST_F(DatasrcConfiguratorTest, rollbackAddition) {
- doInInit();
- // The configuration is wrong. However, the CH one will get done first.
- const ElementPtr
- config(Element::fromJSON("{\"IN\": [{\"type\": 13}], "
- "\"CH\": [{\"type\": \"xxx\"}]}"));
- session.addMessage(createCommand("config_update", config), "data_sources",
- "*");
- log_ = "";
- // It does not throw, as it is handled in the ModuleCCSession.
- // Throwing from the reconfigure is checked in other tests.
- EXPECT_NO_THROW(mccs->checkCommand());
- // Anyway, the result should not contain CH now and the original IN should
- // be there.
- EXPECT_EQ("xxx", lists_[RRClass::IN()]->getConf());
- EXPECT_FALSE(lists_[RRClass::CH()]);
- }
- // Check that we can rollback a deletion if something else fails
- TEST_F(DatasrcConfiguratorTest, rollbackDeletion) {
- doInInit();
- // Put the CH there
- const ElementPtr
- config1(Element::fromJSON("{\"IN\": [{\"type\": \"yyy\"}], "
- "\"CH\": [{\"type\": \"xxx\"}]}"));
- Configurator::reconfigure(config1);
- const ElementPtr
- config2(Element::fromJSON("{\"IN\": [{\"type\": 13}]}"));
- // This would delete CH. However, the IN one fails.
- // As the deletions happen after the additions/settings
- // and there's no known way to cause an exception during the
- // deletions, it is not a true rollback, but the result should
- // be the same.
- EXPECT_THROW(Configurator::reconfigure(config2), TypeError);
- EXPECT_EQ("yyy", lists_[RRClass::IN()]->getConf());
- EXPECT_EQ("xxx", lists_[RRClass::CH()]->getConf());
- }
- // Check that we can roll back configuration change if something
- // fails later on.
- TEST_F(DatasrcConfiguratorTest, rollbackConfiguration) {
- doInInit();
- // Put the CH there
- const ElementPtr
- config1(Element::fromJSON("{\"IN\": [{\"type\": \"yyy\"}], "
- "\"CH\": [{\"type\": \"xxx\"}]}"));
- Configurator::reconfigure(config1);
- // Now, the CH happens first. But nevertheless, it should be
- // restored to the previoeus version.
- const ElementPtr
- config2(Element::fromJSON("{\"IN\": [{\"type\": 13}], "
- "\"CH\": [{\"type\": \"yyy\"}]}"));
- EXPECT_THROW(Configurator::reconfigure(config2), TypeError);
- EXPECT_EQ("yyy", lists_[RRClass::IN()]->getConf());
- EXPECT_EQ("xxx", lists_[RRClass::CH()]->getConf());
- }
- }
|