client_list_unittest.cc 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <datasrc/client_list.h>
  15. #include <datasrc/client.h>
  16. #include <datasrc/cache_config.h>
  17. #include <datasrc/zone_iterator.h>
  18. #include <datasrc/exceptions.h>
  19. #include <datasrc/memory/memory_client.h>
  20. #include <datasrc/memory/zone_table_segment.h>
  21. #include <datasrc/memory/zone_finder.h>
  22. #include <datasrc/memory/zone_writer.h>
  23. #include <datasrc/tests/mock_client.h>
  24. #include <dns/rrclass.h>
  25. #include <dns/rrttl.h>
  26. #include <dns/rdataclass.h>
  27. #include <gtest/gtest.h>
  28. #include <boost/shared_ptr.hpp>
  29. #include <set>
  30. #include <fstream>
  31. using namespace isc::datasrc;
  32. using isc::datasrc::unittest::MockDataSourceClient;
  33. using isc::datasrc::memory::InMemoryClient;
  34. using isc::datasrc::memory::ZoneTableSegment;
  35. using isc::datasrc::memory::InMemoryZoneFinder;
  36. using namespace isc::data;
  37. using namespace isc::dns;
  38. // don't import the entire boost namespace. It will unexpectedly hide uintXX_t
  39. // for some systems.
  40. using boost::shared_ptr;
  41. using namespace std;
  42. namespace {
  43. // The test version is the same as the normal version. We, however, add
  44. // some methods to dig directly in the internals, for the tests.
  45. class TestedList : public ConfigurableClientList {
  46. public:
  47. TestedList(const RRClass& rrclass) :
  48. ConfigurableClientList(rrclass)
  49. {}
  50. DataSources& getDataSources() { return (data_sources_); }
  51. // Overwrite the list's method to get a data source with given type
  52. // and configuration. We mock the data source and don't create the
  53. // container. This is just to avoid some complexity in the tests.
  54. virtual DataSourcePair getDataSourceClient(const string& type,
  55. const ConstElementPtr&
  56. configuration)
  57. {
  58. if (type == "error") {
  59. isc_throw(DataSourceError, "The error data source type");
  60. }
  61. if (type == "MasterFiles") {
  62. return (DataSourcePair(0, DataSourceClientContainerPtr()));
  63. }
  64. shared_ptr<MockDataSourceClient>
  65. ds(new MockDataSourceClient(type, configuration));
  66. // Make sure it is deleted when the test list is deleted.
  67. to_delete_.push_back(ds);
  68. return (DataSourcePair(ds.get(), DataSourceClientContainerPtr()));
  69. }
  70. private:
  71. // Hold list of data sources created internally, so they are preserved
  72. // until the end of the test and then deleted.
  73. vector<shared_ptr<MockDataSourceClient> > to_delete_;
  74. };
  75. const char* ds_zones[][3] = {
  76. {
  77. "example.org.",
  78. "example.com.",
  79. NULL
  80. },
  81. {
  82. "sub.example.org.",
  83. NULL, NULL
  84. },
  85. {
  86. NULL, NULL, NULL
  87. },
  88. {
  89. "sub.example.org.",
  90. NULL, NULL
  91. }
  92. };
  93. const size_t ds_count = (sizeof(ds_zones) / sizeof(*ds_zones));
  94. class ListTest : public ::testing::Test {
  95. public:
  96. ListTest() :
  97. rrclass_(RRClass::IN()),
  98. // The empty list corresponds to a list with no elements inside
  99. list_(new TestedList(rrclass_)),
  100. config_elem_(Element::fromJSON("["
  101. "{"
  102. " \"type\": \"test_type\","
  103. " \"params\": {}"
  104. "}]")),
  105. config_elem_zones_(Element::fromJSON("["
  106. "{"
  107. " \"type\": \"test_type\","
  108. " \"params\": [\"example.org\", \"example.com\", "
  109. " \"noiter.org\", \"null.org\"]"
  110. "}]")),
  111. ztable_segment_(ZoneTableSegment::create(rrclass_, "local"))
  112. {
  113. for (size_t i(0); i < ds_count; ++ i) {
  114. shared_ptr<MockDataSourceClient>
  115. ds(new MockDataSourceClient(ds_zones[i]));
  116. ds_.push_back(ds);
  117. ds_info_.push_back(ConfigurableClientList::DataSourceInfo(
  118. ds.get(), DataSourceClientContainerPtr(),
  119. boost::shared_ptr<internal::CacheConfig>(),
  120. rrclass_, ""));
  121. }
  122. }
  123. // Install a "fake" cached zone using a temporary underlying data source
  124. // client. If 'enabled' is set to false, emulate a disabled cache, in
  125. // which case there will be no data in memory.
  126. void prepareCache(size_t index, const Name& zone, bool enabled = true) {
  127. ConfigurableClientList::DataSourceInfo& dsrc_info =
  128. list_->getDataSources()[index];
  129. MockDataSourceClient* mock_client =
  130. static_cast<MockDataSourceClient*>(dsrc_info.data_src_client_);
  131. // Disable some default features of the mock to distinguish the
  132. // temporary case from normal case.
  133. mock_client->disableA();
  134. mock_client->disableBadIterator();
  135. // Build new cache config to load the specified zone, and replace
  136. // the data source info with the new config.
  137. ConstElementPtr cache_conf_elem =
  138. Element::fromJSON("{\"type\": \"mock\","
  139. " \"cache-enable\": " +
  140. string(enabled ? "true," : "false,") +
  141. " \"cache-zones\": "
  142. " [\"" + zone.toText() + "\"]}");
  143. boost::shared_ptr<internal::CacheConfig> cache_conf(
  144. new internal::CacheConfig("mock", mock_client, *cache_conf_elem,
  145. true));
  146. dsrc_info = ConfigurableClientList::DataSourceInfo(
  147. dsrc_info.data_src_client_,
  148. dsrc_info.container_,
  149. cache_conf, rrclass_, dsrc_info.name_);
  150. // Load the data into the zone table.
  151. if (enabled) {
  152. boost::scoped_ptr<memory::ZoneWriter> writer(
  153. new memory::ZoneWriter(&(*dsrc_info.ztable_segment_),
  154. cache_conf->getLoadAction(rrclass_, zone),
  155. zone, rrclass_));
  156. writer->load();
  157. writer->install();
  158. writer->cleanup(); // not absolutely necessary, but just in case
  159. }
  160. // On completion of load revert to the previous state of underlying
  161. // data source.
  162. mock_client->enableA();
  163. mock_client->enableBadIterator();
  164. }
  165. // Check the positive result is as we expect it.
  166. void positiveResult(const ClientList::FindResult& result,
  167. const shared_ptr<MockDataSourceClient>& dsrc,
  168. const Name& name, bool exact,
  169. const char* test, bool from_cache = false)
  170. {
  171. SCOPED_TRACE(test);
  172. ASSERT_NE(ZoneFinderPtr(), result.finder_);
  173. EXPECT_EQ(name, result.finder_->getOrigin());
  174. EXPECT_EQ(exact, result.exact_match_);
  175. // If it is a positive result, there's something to keep
  176. // alive, even when we don't know what it is.
  177. // Any better idea how to test it actually keeps the thing
  178. // alive?
  179. EXPECT_NE(shared_ptr<ClientList::FindResult::LifeKeeper>(),
  180. result.life_keeper_);
  181. if (from_cache) {
  182. EXPECT_NE(shared_ptr<InMemoryZoneFinder>(),
  183. boost::dynamic_pointer_cast<InMemoryZoneFinder>(
  184. result.finder_)) << "Finder is not from cache";
  185. EXPECT_TRUE(NULL !=
  186. dynamic_cast<InMemoryClient*>(result.dsrc_client_));
  187. } else {
  188. EXPECT_EQ(dsrc.get(), result.dsrc_client_);
  189. }
  190. }
  191. // Configure the list with multiple data sources, according to
  192. // some configuration. It uses the index as parameter, to be able to
  193. // loop through the configurations.
  194. void multiConfiguration(size_t index) {
  195. list_->getDataSources().clear();
  196. switch (index) {
  197. case 2:
  198. list_->getDataSources().push_back(ds_info_[2]);
  199. // The ds_[2] is empty. We just check that it doesn't confuse
  200. // us. Fall through to the case 0.
  201. case 0:
  202. list_->getDataSources().push_back(ds_info_[0]);
  203. list_->getDataSources().push_back(ds_info_[1]);
  204. break;
  205. case 1:
  206. // The other order
  207. list_->getDataSources().push_back(ds_info_[1]);
  208. list_->getDataSources().push_back(ds_info_[0]);
  209. break;
  210. case 3:
  211. list_->getDataSources().push_back(ds_info_[1]);
  212. list_->getDataSources().push_back(ds_info_[0]);
  213. // It is the same as ds_[1], but we take from the first one.
  214. // The first one to match is the correct one.
  215. list_->getDataSources().push_back(ds_info_[3]);
  216. break;
  217. default:
  218. FAIL() << "Unknown configuration index " << index;
  219. }
  220. }
  221. void checkDS(size_t index, const string& type, const string& params,
  222. bool cache) const
  223. {
  224. ASSERT_GT(list_->getDataSources().size(), index);
  225. MockDataSourceClient* ds(dynamic_cast<MockDataSourceClient*>(
  226. list_->getDataSources()[index].data_src_client_));
  227. // Comparing with NULL does not work
  228. ASSERT_NE(ds, static_cast<const MockDataSourceClient*>(NULL));
  229. EXPECT_EQ(type, ds->type_);
  230. EXPECT_TRUE(Element::fromJSON(params)->equals(*ds->configuration_));
  231. EXPECT_EQ(cache, list_->getDataSources()[index].cache_ !=
  232. shared_ptr<InMemoryClient>());
  233. }
  234. const RRClass rrclass_;
  235. shared_ptr<TestedList> list_;
  236. const ClientList::FindResult negative_result_;
  237. vector<shared_ptr<MockDataSourceClient> > ds_;
  238. vector<ConfigurableClientList::DataSourceInfo> ds_info_;
  239. const ConstElementPtr config_elem_, config_elem_zones_;
  240. shared_ptr<ZoneTableSegment> ztable_segment_;
  241. };
  242. // Test the test itself
  243. TEST_F(ListTest, selfTest) {
  244. EXPECT_EQ(result::SUCCESS, ds_[0]->findZone(Name("example.org")).code);
  245. EXPECT_EQ(result::PARTIALMATCH,
  246. ds_[0]->findZone(Name("sub.example.org")).code);
  247. EXPECT_EQ(result::NOTFOUND, ds_[0]->findZone(Name("org")).code);
  248. EXPECT_EQ(result::NOTFOUND, ds_[1]->findZone(Name("example.org")).code);
  249. EXPECT_EQ(result::NOTFOUND, ds_[0]->findZone(Name("aaa")).code);
  250. EXPECT_EQ(result::NOTFOUND, ds_[0]->findZone(Name("zzz")).code);
  251. // Nothing to keep alive here.
  252. EXPECT_EQ(shared_ptr<ClientList::FindResult::LifeKeeper>(),
  253. negative_result_.life_keeper_);
  254. }
  255. // Test the list we create with empty configuration is, in fact, empty
  256. TEST_F(ListTest, emptyList) {
  257. EXPECT_TRUE(list_->getDataSources().empty());
  258. }
  259. // Check the values returned by a find on an empty list. It should be
  260. // a negative answer (nothing found) no matter if we want an exact or inexact
  261. // match.
  262. TEST_F(ListTest, emptySearch) {
  263. // No matter what we try, we don't get an answer.
  264. // Note: we don't have operator<< for the result class, so we cannot use
  265. // EXPECT_EQ. Same for other similar cases.
  266. EXPECT_TRUE(negative_result_ == list_->find(Name("example.org"), false,
  267. false));
  268. EXPECT_TRUE(negative_result_ == list_->find(Name("example.org"), false,
  269. true));
  270. EXPECT_TRUE(negative_result_ == list_->find(Name("example.org"), true,
  271. false));
  272. EXPECT_TRUE(negative_result_ == list_->find(Name("example.org"), true,
  273. true));
  274. }
  275. // Put a single data source inside the list and check it can find an
  276. // exact match if there's one.
  277. TEST_F(ListTest, singleDSExactMatch) {
  278. list_->getDataSources().push_back(ds_info_[0]);
  279. // This zone is not there
  280. EXPECT_TRUE(negative_result_ == list_->find(Name("org."), true));
  281. // But this one is, so check it.
  282. positiveResult(list_->find(Name("example.org"), true), ds_[0],
  283. Name("example.org"), true, "Exact match");
  284. // When asking for a sub zone of a zone there, we get nothing
  285. // (we want exact match, this would be partial one)
  286. EXPECT_TRUE(negative_result_ == list_->find(Name("sub.example.org."),
  287. true));
  288. }
  289. // When asking for a partial match, we get all that the exact one, but more.
  290. TEST_F(ListTest, singleDSBestMatch) {
  291. list_->getDataSources().push_back(ds_info_[0]);
  292. // This zone is not there
  293. EXPECT_TRUE(negative_result_ == list_->find(Name("org.")));
  294. // But this one is, so check it.
  295. positiveResult(list_->find(Name("example.org")), ds_[0],
  296. Name("example.org"), true, "Exact match");
  297. // When asking for a sub zone of a zone there, we get the parent
  298. // one.
  299. positiveResult(list_->find(Name("sub.example.org.")), ds_[0],
  300. Name("example.org"), false, "Subdomain match");
  301. }
  302. const char* const test_names[] = {
  303. "Sub second",
  304. "Sub first",
  305. "With empty",
  306. "With a duplicity"
  307. };
  308. TEST_F(ListTest, multiExactMatch) {
  309. // Run through all the multi-configurations
  310. for (size_t i(0); i < sizeof(test_names) / sizeof(*test_names); ++i) {
  311. SCOPED_TRACE(test_names[i]);
  312. multiConfiguration(i);
  313. // Something that is nowhere there
  314. EXPECT_TRUE(negative_result_ == list_->find(Name("org."), true));
  315. // This one is there exactly.
  316. positiveResult(list_->find(Name("example.org"), true), ds_[0],
  317. Name("example.org"), true, "Exact match");
  318. // This one too, but in a different data source.
  319. positiveResult(list_->find(Name("sub.example.org."), true), ds_[1],
  320. Name("sub.example.org"), true, "Subdomain match");
  321. // But this one is in neither data source.
  322. EXPECT_TRUE(negative_result_ ==
  323. list_->find(Name("sub.example.com."), true));
  324. }
  325. }
  326. TEST_F(ListTest, multiBestMatch) {
  327. // Run through all the multi-configurations
  328. for (size_t i(0); i < 4; ++ i) {
  329. SCOPED_TRACE(test_names[i]);
  330. multiConfiguration(i);
  331. // Something that is nowhere there
  332. EXPECT_TRUE(negative_result_ == list_->find(Name("org.")));
  333. // This one is there exactly.
  334. positiveResult(list_->find(Name("example.org")), ds_[0],
  335. Name("example.org"), true, "Exact match");
  336. // This one too, but in a different data source.
  337. positiveResult(list_->find(Name("sub.example.org.")), ds_[1],
  338. Name("sub.example.org"), true, "Subdomain match");
  339. // But this one is in neither data source. But it is a subdomain
  340. // of one of the zones in the first data source.
  341. positiveResult(list_->find(Name("sub.example.com.")), ds_[0],
  342. Name("example.com."), false, "Subdomain in com");
  343. }
  344. }
  345. // Check the configuration is empty when the list is empty
  346. TEST_F(ListTest, configureEmpty) {
  347. const ConstElementPtr elem(new ListElement);
  348. list_->configure(elem, true);
  349. EXPECT_TRUE(list_->getDataSources().empty());
  350. // Check the exact configuration is preserved
  351. EXPECT_EQ(elem, list_->getConfiguration());
  352. }
  353. // Check we can get multiple data sources and they are in the right order.
  354. TEST_F(ListTest, configureMulti) {
  355. const ConstElementPtr elem(Element::fromJSON("["
  356. "{"
  357. " \"type\": \"type1\","
  358. " \"cache-enable\": false,"
  359. " \"params\": {}"
  360. "},"
  361. "{"
  362. " \"type\": \"type2\","
  363. " \"cache-enable\": false,"
  364. " \"params\": {}"
  365. "}]"
  366. ));
  367. list_->configure(elem, true);
  368. EXPECT_EQ(2, list_->getDataSources().size());
  369. checkDS(0, "type1", "{}", false);
  370. checkDS(1, "type2", "{}", false);
  371. // Check the exact configuration is preserved
  372. EXPECT_EQ(elem, list_->getConfiguration());
  373. }
  374. // Check we can pass whatever we want to the params
  375. TEST_F(ListTest, configureParams) {
  376. const char* params[] = {
  377. "true",
  378. "false",
  379. "null",
  380. "\"hello\"",
  381. "42",
  382. "[]",
  383. "{}",
  384. NULL
  385. };
  386. for (const char** param(params); *param; ++param) {
  387. SCOPED_TRACE(*param);
  388. ConstElementPtr elem(Element::fromJSON(string("["
  389. "{"
  390. " \"type\": \"t\","
  391. " \"cache-enable\": false,"
  392. " \"params\": ") + *param +
  393. "}]"));
  394. list_->configure(elem, true);
  395. EXPECT_EQ(1, list_->getDataSources().size());
  396. checkDS(0, "t", *param, false);
  397. }
  398. }
  399. TEST_F(ListTest, status) {
  400. EXPECT_TRUE(list_->getStatus().empty());
  401. const ConstElementPtr elem(Element::fromJSON("["
  402. "{"
  403. " \"type\": \"type1\","
  404. " \"cache-enable\": false,"
  405. " \"params\": {}"
  406. "},"
  407. "{"
  408. " \"type\": \"type2\","
  409. " \"cache-enable\": true,"
  410. " \"cache-zones\": [],"
  411. " \"name\": \"Test name\","
  412. " \"params\": {}"
  413. "}]"
  414. ));
  415. list_->configure(elem, true);
  416. const vector<DataSourceStatus> statuses(list_->getStatus());
  417. ASSERT_EQ(2, statuses.size());
  418. EXPECT_EQ("type1", statuses[0].getName());
  419. EXPECT_EQ(SEGMENT_UNUSED, statuses[0].getSegmentState());
  420. EXPECT_THROW(statuses[0].getSegmentType(), isc::InvalidOperation);
  421. EXPECT_EQ("Test name", statuses[1].getName());
  422. EXPECT_EQ(SEGMENT_INUSE, statuses[1].getSegmentState());
  423. EXPECT_EQ("local", statuses[1].getSegmentType());
  424. }
  425. TEST_F(ListTest, wrongConfig) {
  426. const char* configs[] = {
  427. // A lot of stuff missing from there
  428. "[{\"type\": \"test_type\", \"params\": 13}, {}]",
  429. // Some bad types completely
  430. "{}",
  431. "true",
  432. "42",
  433. "null",
  434. "[{\"type\": \"test_type\", \"params\": 13}, true]",
  435. "[{\"type\": \"test_type\", \"params\": 13}, []]",
  436. "[{\"type\": \"test_type\", \"params\": 13}, 42]",
  437. // Bad type of type
  438. "[{\"type\": \"test_type\", \"params\": 13}, {\"type\": 42}]",
  439. "[{\"type\": \"test_type\", \"params\": 13}, {\"type\": true}]",
  440. "[{\"type\": \"test_type\", \"params\": 13}, {\"type\": null}]",
  441. "[{\"type\": \"test_type\", \"params\": 13}, {\"type\": []}]",
  442. "[{\"type\": \"test_type\", \"params\": 13}, {\"type\": {}}]",
  443. // Bad type of cache-enable
  444. "[{\"type\": \"test_type\", \"params\": 13}, "
  445. "{\"type\": \"x\", \"cache-enable\": 13, \"cache-zones\": []}]",
  446. "[{\"type\": \"test_type\", \"params\": 13}, "
  447. "{\"type\": \"x\", \"cache-enable\": \"xx\", \"cache-zones\": []}]",
  448. "[{\"type\": \"test_type\", \"params\": 13}, "
  449. "{\"type\": \"x\", \"cache-enable\": [], \"cache-zones\": []}]",
  450. "[{\"type\": \"test_type\", \"params\": 13}, "
  451. "{\"type\": \"x\", \"cache-enable\": {}, \"cache-zones\": []}]",
  452. "[{\"type\": \"test_type\", \"params\": 13}, "
  453. "{\"type\": \"x\", \"cache-enable\": null, \"cache-zones\": []}]",
  454. // Bad type of cache-zones
  455. "[{\"type\": \"test_type\", \"params\": 13}, "
  456. "{\"type\": \"x\", \"cache-enable\": true, \"cache-zones\": \"x\"}]",
  457. "[{\"type\": \"test_type\", \"params\": 13}, "
  458. "{\"type\": \"x\", \"cache-enable\": true, \"cache-zones\": true}]",
  459. "[{\"type\": \"test_type\", \"params\": 13}, "
  460. "{\"type\": \"x\", \"cache-enable\": true, \"cache-zones\": null}]",
  461. "[{\"type\": \"test_type\", \"params\": 13}, "
  462. "{\"type\": \"x\", \"cache-enable\": true, \"cache-zones\": 13}]",
  463. "[{\"type\": \"test_type\", \"params\": 13}, "
  464. "{\"type\": \"x\", \"cache-enable\": true, \"cache-zones\": {}}]",
  465. // Some bad inputs for MasterFiles special case
  466. // It must have the cache enabled
  467. "[{\"type\": \"test_type\", \"params\": 13}, "
  468. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  469. "\"params\": {}}]",
  470. // No cache-zones allowed here
  471. "[{\"type\": \"test_type\", \"params\": 13}, "
  472. "{\"type\": \"MasterFiles\", \"cache-enable\": true,"
  473. "\"param\": {}, \"cache-zones\": []}]",
  474. // Some bad types of params
  475. "[{\"type\": \"test_type\", \"params\": 13}, "
  476. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  477. "\"params\": []}]",
  478. "[{\"type\": \"test_type\", \"params\": 13}, "
  479. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  480. "\"params\": 13}]",
  481. "[{\"type\": \"test_type\", \"params\": 13}, "
  482. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  483. "\"params\": true}]",
  484. "[{\"type\": \"test_type\", \"params\": 13}, "
  485. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  486. "\"params\": null}]",
  487. "[{\"type\": \"test_type\", \"params\": 13}, "
  488. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  489. "\"params\": \"x\"}]",
  490. "[{\"type\": \"test_type\", \"params\": 13}, "
  491. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  492. "\"params\": {\".\": 13}}]",
  493. "[{\"type\": \"test_type\", \"params\": 13}, "
  494. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  495. "\"params\": {\".\": true}}]",
  496. "[{\"type\": \"test_type\", \"params\": 13}, "
  497. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  498. "\"params\": {\".\": null}}]",
  499. "[{\"type\": \"test_type\", \"params\": 13}, "
  500. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  501. "\"params\": {\".\": []}}]",
  502. "[{\"type\": \"test_type\", \"params\": 13}, "
  503. "{\"type\": \"MasterFiles\", \"cache-enable\": false,"
  504. "\"params\": {\".\": {}}}]",
  505. NULL
  506. };
  507. // Put something inside to see it survives the exception
  508. list_->configure(config_elem_, true);
  509. checkDS(0, "test_type", "{}", false);
  510. for (const char** config(configs); *config; ++config) {
  511. SCOPED_TRACE(*config);
  512. ConstElementPtr elem(Element::fromJSON(*config));
  513. EXPECT_THROW(list_->configure(elem, true),
  514. ConfigurableClientList::ConfigurationError);
  515. // Still untouched
  516. checkDS(0, "test_type", "{}", false);
  517. EXPECT_EQ(1, list_->getDataSources().size());
  518. }
  519. }
  520. // The param thing defaults to null. Cache is not used yet.
  521. TEST_F(ListTest, defaults) {
  522. const ConstElementPtr elem(Element::fromJSON("["
  523. "{"
  524. " \"type\": \"type1\""
  525. "}]"));
  526. list_->configure(elem, true);
  527. EXPECT_EQ(1, list_->getDataSources().size());
  528. checkDS(0, "type1", "null", false);
  529. }
  530. // Check we can call the configure multiple times, to change the configuration
  531. TEST_F(ListTest, reconfigure) {
  532. const ConstElementPtr empty(new ListElement);
  533. list_->configure(config_elem_, true);
  534. checkDS(0, "test_type", "{}", false);
  535. list_->configure(empty, true);
  536. EXPECT_TRUE(list_->getDataSources().empty());
  537. list_->configure(config_elem_, true);
  538. checkDS(0, "test_type", "{}", false);
  539. }
  540. // Make sure the data source error exception from the factory is propagated
  541. TEST_F(ListTest, dataSrcError) {
  542. const ConstElementPtr elem(Element::fromJSON("["
  543. "{"
  544. " \"type\": \"error\""
  545. "}]"));
  546. list_->configure(config_elem_, true);
  547. checkDS(0, "test_type", "{}", false);
  548. EXPECT_THROW(list_->configure(elem, true), DataSourceError);
  549. checkDS(0, "test_type", "{}", false);
  550. }
  551. // Check we can get the cache
  552. TEST_F(ListTest, configureCacheEmpty) {
  553. const ConstElementPtr elem(Element::fromJSON("["
  554. "{"
  555. " \"type\": \"type1\","
  556. " \"cache-enable\": true,"
  557. " \"cache-zones\": [],"
  558. " \"params\": {}"
  559. "},"
  560. "{"
  561. " \"type\": \"type2\","
  562. " \"cache-enable\": false,"
  563. " \"cache-zones\": [],"
  564. " \"params\": {}"
  565. "}]"
  566. ));
  567. list_->configure(elem, true);
  568. EXPECT_EQ(2, list_->getDataSources().size());
  569. checkDS(0, "type1", "{}", true);
  570. checkDS(1, "type2", "{}", false);
  571. }
  572. // But no cache if we disallow it globally
  573. TEST_F(ListTest, configureCacheDisabled) {
  574. const ConstElementPtr elem(Element::fromJSON("["
  575. "{"
  576. " \"type\": \"type1\","
  577. " \"cache-enable\": true,"
  578. " \"cache-zones\": [],"
  579. " \"params\": {}"
  580. "},"
  581. "{"
  582. " \"type\": \"type2\","
  583. " \"cache-enable\": false,"
  584. " \"cache-zones\": [],"
  585. " \"params\": {}"
  586. "}]"
  587. ));
  588. list_->configure(elem, false);
  589. EXPECT_EQ(2, list_->getDataSources().size());
  590. checkDS(0, "type1", "{}", false);
  591. checkDS(1, "type2", "{}", false);
  592. }
  593. // Put some zones into the cache
  594. TEST_F(ListTest, cacheZones) {
  595. const ConstElementPtr elem(Element::fromJSON("["
  596. "{"
  597. " \"type\": \"type1\","
  598. " \"cache-enable\": true,"
  599. " \"cache-zones\": [\"example.org\", \"example.com\"],"
  600. " \"params\": [\"example.org\", \"example.com\", \"exmaple.cz\"]"
  601. "}]"));
  602. list_->configure(elem, true);
  603. checkDS(0, "type1", "[\"example.org\", \"example.com\", \"exmaple.cz\"]",
  604. true);
  605. const shared_ptr<InMemoryClient> cache(list_->getDataSources()[0].cache_);
  606. EXPECT_EQ(2, cache->getZoneCount());
  607. EXPECT_EQ(result::SUCCESS, cache->findZone(Name("example.org")).code);
  608. EXPECT_EQ(result::SUCCESS, cache->findZone(Name("example.com")).code);
  609. EXPECT_EQ(result::NOTFOUND, cache->findZone(Name("example.cz")).code);
  610. EXPECT_EQ(RRClass::IN(),
  611. cache->findZone(Name("example.org")).zone_finder->getClass());
  612. // These are cached and answered from the cache
  613. positiveResult(list_->find(Name("example.com.")), ds_[0],
  614. Name("example.com."), true, "com", true);
  615. positiveResult(list_->find(Name("example.org.")), ds_[0],
  616. Name("example.org."), true, "org", true);
  617. positiveResult(list_->find(Name("sub.example.com.")), ds_[0],
  618. Name("example.com."), false, "Subdomain of com", true);
  619. // For now, the ones not cached are ignored.
  620. EXPECT_TRUE(negative_result_ == list_->find(Name("example.cz.")));
  621. }
  622. // Check the caching handles misbehaviour from the data source and
  623. // misconfiguration gracefully
  624. TEST_F(ListTest, badCache) {
  625. list_->configure(config_elem_, true);
  626. checkDS(0, "test_type", "{}", false);
  627. // First, the zone is not in the data source
  628. const ConstElementPtr elem1(Element::fromJSON("["
  629. "{"
  630. " \"type\": \"type1\","
  631. " \"cache-enable\": true,"
  632. " \"cache-zones\": [\"example.org\"],"
  633. " \"params\": []"
  634. "}]"));
  635. EXPECT_THROW(list_->configure(elem1, true),
  636. ConfigurableClientList::ConfigurationError);
  637. checkDS(0, "test_type", "{}", false);
  638. // Now, the zone doesn't give an iterator
  639. const ConstElementPtr elem2(Element::fromJSON("["
  640. "{"
  641. " \"type\": \"type1\","
  642. " \"cache-enable\": true,"
  643. " \"cache-zones\": [\"noiter.org\"],"
  644. " \"params\": [\"noiter.org\"]"
  645. "}]"));
  646. EXPECT_THROW(list_->configure(elem2, true), isc::NotImplemented);
  647. checkDS(0, "test_type", "{}", false);
  648. // Now, the zone returns NULL iterator
  649. const ConstElementPtr elem3(Element::fromJSON("["
  650. "{"
  651. " \"type\": \"type1\","
  652. " \"cache-enable\": true,"
  653. " \"cache-zones\": [\"null.org\"],"
  654. " \"params\": [\"null.org\"]"
  655. "}]"));
  656. EXPECT_THROW(list_->configure(elem3, true), isc::Unexpected);
  657. checkDS(0, "test_type", "{}", false);
  658. // The autodetection of zones is not enabled
  659. const ConstElementPtr elem4(Element::fromJSON("["
  660. "{"
  661. " \"type\": \"type1\","
  662. " \"cache-enable\": true,"
  663. " \"params\": [\"example.org\"]"
  664. "}]"));
  665. EXPECT_THROW(list_->configure(elem4, true), isc::NotImplemented);
  666. checkDS(0, "test_type", "{}", false);
  667. }
  668. TEST_F(ListTest, masterFiles) {
  669. const ConstElementPtr elem(Element::fromJSON("["
  670. "{"
  671. " \"type\": \"MasterFiles\","
  672. " \"cache-enable\": true,"
  673. " \"params\": {"
  674. " \".\": \"" TEST_DATA_DIR "/root.zone\""
  675. " }"
  676. "}]"));
  677. list_->configure(elem, true);
  678. // It has only the cache
  679. EXPECT_EQ(static_cast<const DataSourceClient*>(NULL),
  680. list_->getDataSources()[0].data_src_client_);
  681. // And it can search
  682. positiveResult(list_->find(Name(".")), ds_[0], Name("."), true, "com",
  683. true);
  684. // If cache is not enabled, nothing is loaded
  685. list_->configure(elem, false);
  686. EXPECT_EQ(0, list_->getDataSources().size());
  687. }
  688. // Test the names are set correctly and collission is detected.
  689. TEST_F(ListTest, names) {
  690. // Explicit name
  691. const ConstElementPtr elem1(Element::fromJSON("["
  692. "{"
  693. " \"type\": \"MasterFiles\","
  694. " \"cache-enable\": true,"
  695. " \"params\": {"
  696. " \".\": \"" TEST_DATA_DIR "/root.zone\""
  697. " },"
  698. " \"name\": \"Whatever\""
  699. "}]"));
  700. list_->configure(elem1, true);
  701. EXPECT_EQ("Whatever", list_->getDataSources()[0].name_);
  702. // Default name
  703. const ConstElementPtr elem2(Element::fromJSON("["
  704. "{"
  705. " \"type\": \"MasterFiles\","
  706. " \"cache-enable\": true,"
  707. " \"params\": {"
  708. " \".\": \"" TEST_DATA_DIR "/root.zone\""
  709. " }"
  710. "}]"));
  711. list_->configure(elem2, true);
  712. EXPECT_EQ("MasterFiles", list_->getDataSources()[0].name_);
  713. // Collission
  714. const ConstElementPtr elem3(Element::fromJSON("["
  715. "{"
  716. " \"type\": \"MasterFiles\","
  717. " \"cache-enable\": true,"
  718. " \"params\": {"
  719. " \".\": \"" TEST_DATA_DIR "/root.zone\""
  720. " }"
  721. "},"
  722. "{"
  723. " \"type\": \"MasterFiles\","
  724. " \"cache-enable\": true,"
  725. " \"params\": {"
  726. " \".\": \"" TEST_DATA_DIR "/root.zone\""
  727. " },"
  728. " \"name\": \"MasterFiles\""
  729. "}]"));
  730. EXPECT_THROW(list_->configure(elem3, true),
  731. ConfigurableClientList::ConfigurationError);
  732. }
  733. TEST_F(ListTest, BadMasterFile) {
  734. // Configuration should succeed, and the good zones in the list
  735. // below should be loaded. No bad zones should be loaded.
  736. const ConstElementPtr elem(Element::fromJSON("["
  737. "{"
  738. " \"type\": \"MasterFiles\","
  739. " \"cache-enable\": true,"
  740. " \"params\": {"
  741. // good zone
  742. " \"example.com.\": \"" TEST_DATA_DIR "/example.com.flattened\","
  743. // bad zone (empty file)
  744. " \"example.net.\": \"" TEST_DATA_DIR "/example.net-empty\","
  745. // bad zone (data doesn't validate: see the file for details)
  746. " \"example.edu.\": \"" TEST_DATA_DIR "/example.edu-broken\","
  747. // bad zone (file doesn't exist)
  748. " \"example.info.\": \"" TEST_DATA_DIR "/example.info-nonexist\","
  749. // bad zone (data doesn't match the zone name)
  750. " \"foo.bar.\": \"" TEST_DATA_DIR "/example.org.nsec3-signed\","
  751. // good zone
  752. " \".\": \"" TEST_DATA_DIR "/root.zone\""
  753. " }"
  754. "}]"));
  755. EXPECT_NO_THROW({
  756. // This should not throw even if there are any zone loading
  757. // errors.
  758. list_->configure(elem, true);
  759. });
  760. positiveResult(list_->find(Name("example.com."), true), ds_[0],
  761. Name("example.com."), true, "example.com", true);
  762. EXPECT_TRUE(negative_result_ == list_->find(Name("example.org."), true));
  763. EXPECT_TRUE(negative_result_ == list_->find(Name("foo.bar"), true));
  764. EXPECT_TRUE(negative_result_ == list_->find(Name("example.net."), true));
  765. EXPECT_TRUE(negative_result_ == list_->find(Name("example.edu."), true));
  766. EXPECT_TRUE(negative_result_ == list_->find(Name("example.info."), true));
  767. positiveResult(list_->find(Name(".")), ds_[0], Name("."), true, "root",
  768. true);
  769. }
  770. // This allows us to test two versions of the reloading code
  771. // (One by calling reload(), one by obtaining a ZoneWriter and
  772. // playing with that). Once we deprecate reload(), we should revert this
  773. // change and not use typed tests any more.
  774. template<class UpdateType>
  775. class ReloadTest : public ListTest {
  776. public:
  777. ConfigurableClientList::ReloadResult doReload(const Name& origin);
  778. };
  779. // Version with calling reload()
  780. class ReloadUpdateType {};
  781. template<>
  782. ConfigurableClientList::ReloadResult
  783. ReloadTest<ReloadUpdateType>::doReload(const Name& origin) {
  784. return (list_->reload(origin));
  785. };
  786. // Version with the ZoneWriter
  787. class WriterUpdateType {};
  788. template<>
  789. ConfigurableClientList::ReloadResult
  790. ReloadTest<WriterUpdateType>::doReload(const Name& origin) {
  791. ConfigurableClientList::ZoneWriterPair
  792. result(list_->getCachedZoneWriter(origin));
  793. if (result.first == ConfigurableClientList::ZONE_SUCCESS) {
  794. // Can't use ASSERT_NE here, it would want to return(), which
  795. // it can't in non-void function.
  796. if (result.second) {
  797. result.second->load();
  798. result.second->install();
  799. result.second->cleanup();
  800. } else {
  801. ADD_FAILURE() << "getCachedZoneWriter returned ZONE_SUCCESS, "
  802. "but the writer is NULL";
  803. }
  804. } else {
  805. EXPECT_EQ(static_cast<memory::ZoneWriter*>(NULL),
  806. result.second.get());
  807. }
  808. return (result.first);
  809. }
  810. // Typedefs for the GTEST guts to make it work
  811. typedef ::testing::Types<ReloadUpdateType, WriterUpdateType> UpdateTypes;
  812. TYPED_TEST_CASE(ReloadTest, UpdateTypes);
  813. // Test we can reload a zone
  814. TYPED_TEST(ReloadTest, reloadSuccess) {
  815. this->list_->configure(this->config_elem_zones_, true);
  816. const Name name("example.org");
  817. this->prepareCache(0, name);
  818. // The cache currently contains a tweaked version of zone, which
  819. // doesn't have "tstzonedata" A record. So the lookup should result
  820. // in NXDOMAIN.
  821. EXPECT_EQ(ZoneFinder::NXDOMAIN,
  822. this->list_->find(name).finder_->
  823. find(Name("tstzonedata").concatenate(name),
  824. RRType::A())->code);
  825. // Now reload the full zone. It should be there now.
  826. EXPECT_EQ(ConfigurableClientList::ZONE_SUCCESS, this->doReload(name));
  827. EXPECT_EQ(ZoneFinder::SUCCESS,
  828. this->list_->find(name).finder_->
  829. find(Name("tstzonedata").concatenate(name),
  830. RRType::A())->code);
  831. }
  832. // The cache is not enabled. The load should be rejected.
  833. TYPED_TEST(ReloadTest, reloadNotAllowed) {
  834. this->list_->configure(this->config_elem_zones_, false);
  835. const Name name("example.org");
  836. // We put the cache in even when not enabled. This won't confuse the thing.
  837. this->prepareCache(0, name);
  838. // See the reloadSuccess test. This should result in NXDOMAIN.
  839. EXPECT_EQ(ZoneFinder::NXDOMAIN,
  840. this->list_->find(name).finder_->
  841. find(Name("tstzonedata").concatenate(name),
  842. RRType::A())->code);
  843. // Now reload. It should reject it.
  844. EXPECT_EQ(ConfigurableClientList::CACHE_DISABLED, this->doReload(name));
  845. // Nothing changed here
  846. EXPECT_EQ(ZoneFinder::NXDOMAIN,
  847. this->list_->find(name).finder_->
  848. find(Name("tstzonedata").concatenate(name),
  849. RRType::A())->code);
  850. }
  851. // Similar to the previous case, but the cache is disabled in config.
  852. TYPED_TEST(ReloadTest, reloadNotEnabled) {
  853. this->list_->configure(this->config_elem_zones_, true);
  854. const Name name("example.org");
  855. // We put the cache, actually disabling it.
  856. this->prepareCache(0, name, false);
  857. // In this case we cannot really look up due to the limitation of
  858. // the mock implementation. We only check reload fails.
  859. EXPECT_EQ(ConfigurableClientList::ZONE_NOT_CACHED, this->doReload(name));
  860. }
  861. // Test several cases when the zone does not exist
  862. TYPED_TEST(ReloadTest, reloadNoSuchZone) {
  863. this->list_->configure(this->config_elem_zones_, true);
  864. const Name name("example.org");
  865. // We put the cache in even when not enabled. This won't confuse the
  866. // reload method, as that one looks at the real state of things, not
  867. // at the configuration.
  868. this->prepareCache(0, Name("example.com"));
  869. // Not in the data sources
  870. EXPECT_EQ(ConfigurableClientList::ZONE_NOT_FOUND,
  871. this->doReload(Name("exmaple.cz")));
  872. // Not cached
  873. EXPECT_EQ(ConfigurableClientList::ZONE_NOT_FOUND, this->doReload(name));
  874. // Partial match
  875. EXPECT_EQ(ConfigurableClientList::ZONE_NOT_FOUND,
  876. this->doReload(Name("sub.example.com")));
  877. // Nothing changed here - these zones don't exist
  878. EXPECT_EQ(static_cast<isc::datasrc::DataSourceClient*>(NULL),
  879. this->list_->find(name).dsrc_client_);
  880. EXPECT_EQ(static_cast<isc::datasrc::DataSourceClient*>(NULL),
  881. this->list_->find(Name("example.cz")).dsrc_client_);
  882. EXPECT_EQ(static_cast<isc::datasrc::DataSourceClient*>(NULL),
  883. this->list_->find(Name("sub.example.com"), true).dsrc_client_);
  884. // Not reloaded, so A record shouldn't be visible yet.
  885. EXPECT_EQ(ZoneFinder::NXDOMAIN,
  886. this->list_->find(Name("example.com")).finder_->
  887. find(Name("tstzonedata.example.com"),
  888. RRType::A())->code);
  889. }
  890. // Check we gracefuly throw an exception when a zone disappeared in
  891. // the underlying data source when we want to reload it
  892. TYPED_TEST(ReloadTest, reloadZoneGone) {
  893. this->list_->configure(this->config_elem_zones_, true);
  894. const Name name("example.org");
  895. // We put in a cache for non-existent zone. This emulates being loaded
  896. // and then the zone disappearing. We prefill the cache, so we can check
  897. // it.
  898. this->prepareCache(0, name);
  899. // The (cached) zone contains zone's SOA
  900. EXPECT_EQ(ZoneFinder::SUCCESS,
  901. this->list_->find(name).finder_->find(name,
  902. RRType::SOA())->code);
  903. // Remove the zone from the data source.
  904. static_cast<MockDataSourceClient*>(
  905. this->list_->getDataSources()[0].data_src_client_)->eraseZone(name);
  906. // The zone is not there, so abort the reload.
  907. EXPECT_THROW(this->doReload(name), DataSourceError);
  908. // The (cached) zone is not hurt.
  909. EXPECT_EQ(ZoneFinder::SUCCESS,
  910. this->list_->find(name).finder_->find(name,
  911. RRType::SOA())->code);
  912. }
  913. // The underlying data source throws. Check we don't modify the state.
  914. TYPED_TEST(ReloadTest, reloadZoneThrow) {
  915. this->list_->configure(this->config_elem_zones_, true);
  916. const Name name("noiter.org");
  917. this->prepareCache(0, name);
  918. // The zone contains stuff now
  919. EXPECT_EQ(ZoneFinder::SUCCESS,
  920. this->list_->find(name).finder_->find(name,
  921. RRType::SOA())->code);
  922. // The iterator throws, so abort the reload.
  923. EXPECT_THROW(this->doReload(name), isc::NotImplemented);
  924. // The zone is not hurt.
  925. EXPECT_EQ(ZoneFinder::SUCCESS,
  926. this->list_->find(name).finder_->find(name,
  927. RRType::SOA())->code);
  928. }
  929. TYPED_TEST(ReloadTest, reloadNullIterator) {
  930. this->list_->configure(this->config_elem_zones_, true);
  931. const Name name("null.org");
  932. this->prepareCache(0, name);
  933. // The zone contains stuff now
  934. EXPECT_EQ(ZoneFinder::SUCCESS,
  935. this->list_->find(name).finder_->find(name,
  936. RRType::SOA())->code);
  937. // The iterator throws, so abort the reload.
  938. EXPECT_THROW(this->doReload(name), isc::Unexpected);
  939. // The zone is not hurt.
  940. EXPECT_EQ(ZoneFinder::SUCCESS,
  941. this->list_->find(name).finder_->find(name,
  942. RRType::SOA())->code);
  943. }
  944. // Test we can reload the master files too (special-cased)
  945. TYPED_TEST(ReloadTest, reloadMasterFile) {
  946. const char* const install_cmd = INSTALL_PROG " -c " TEST_DATA_DIR
  947. "/root.zone " TEST_DATA_BUILDDIR "/root.zone.copied";
  948. if (system(install_cmd) != 0) {
  949. // any exception will do, this is failure in test setup, but
  950. // nice to show the command that fails, and shouldn't be caught
  951. isc_throw(isc::Exception,
  952. "Error setting up; command failed: " << install_cmd);
  953. }
  954. const ConstElementPtr elem(Element::fromJSON("["
  955. "{"
  956. " \"type\": \"MasterFiles\","
  957. " \"cache-enable\": true,"
  958. " \"params\": {"
  959. " \".\": \"" TEST_DATA_BUILDDIR "/root.zone.copied\""
  960. " }"
  961. "}]"));
  962. this->list_->configure(elem, true);
  963. // Add a record that is not in the zone
  964. EXPECT_EQ(ZoneFinder::NXDOMAIN,
  965. this->list_->find(Name(".")).finder_->find(Name("nosuchdomain"),
  966. RRType::TXT())->code);
  967. ofstream f;
  968. f.open(TEST_DATA_BUILDDIR "/root.zone.copied", ios::out | ios::app);
  969. f << "nosuchdomain.\t\t3600\tIN\tTXT\ttest" << std::endl;
  970. f.close();
  971. // Do the reload.
  972. EXPECT_EQ(ConfigurableClientList::ZONE_SUCCESS, this->doReload(Name(".")));
  973. // It is here now.
  974. EXPECT_EQ(ZoneFinder::SUCCESS,
  975. this->list_->find(Name(".")).finder_->find(Name("nosuchdomain"),
  976. RRType::TXT())->code);
  977. }
  978. // Check the status holds data
  979. TEST(DataSourceStatus, status) {
  980. const DataSourceStatus status("Test", SEGMENT_INUSE, "local");
  981. EXPECT_EQ("Test", status.getName());
  982. EXPECT_EQ(SEGMENT_INUSE, status.getSegmentState());
  983. EXPECT_EQ("local", status.getSegmentType());
  984. const DataSourceStatus status_unused("Unused", SEGMENT_UNUSED, "");
  985. EXPECT_EQ("Unused", status_unused.getName());
  986. EXPECT_EQ(SEGMENT_UNUSED, status_unused.getSegmentState());
  987. EXPECT_THROW(status_unused.getSegmentType(), isc::InvalidOperation);
  988. }
  989. }