cfgmgr_unittest.cc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. // Copyright (C) 2012-2015 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 <config.h>
  15. #include <exceptions/exceptions.h>
  16. #include <dhcp/dhcp6.h>
  17. #include <dhcp/tests/iface_mgr_test_config.h>
  18. #include <dhcpsrv/cfgmgr.h>
  19. #include <dhcpsrv/subnet_id.h>
  20. #include <dhcpsrv/parsers/dhcp_parsers.h>
  21. #include <stats/stats_mgr.h>
  22. #include <gtest/gtest.h>
  23. #include <iostream>
  24. #include <sstream>
  25. #include <arpa/inet.h>
  26. using namespace std;
  27. using namespace isc::asiolink;
  28. using namespace isc::data;
  29. using namespace isc::dhcp;
  30. using namespace isc::dhcp::test;
  31. using namespace isc::util;
  32. using namespace isc::stats;
  33. using namespace isc;
  34. // don't import the entire boost namespace. It will unexpectedly hide uint8_t
  35. // for some systems.
  36. using boost::scoped_ptr;
  37. namespace {
  38. template <typename Storage>
  39. bool isZeroPosition(const Storage& storage, const std::string& param_name) {
  40. Element::Position position = storage.getPosition(param_name);
  41. return ((position.line_ == 0) && (position.pos_ == 0) &&
  42. (position.file_.empty()));
  43. }
  44. // This test verifies that BooleanStorage functions properly.
  45. TEST(ValueStorageTest, BooleanTesting) {
  46. BooleanStorage testStore;
  47. // Verify that we can add and retrieve parameters.
  48. testStore.setParam("firstBool", false, Element::Position("kea.conf", 123, 234));
  49. testStore.setParam("secondBool", true, Element::Position("keax.conf", 10, 20));
  50. EXPECT_FALSE(testStore.getParam("firstBool"));
  51. EXPECT_TRUE(testStore.getParam("secondBool"));
  52. EXPECT_EQ(123, testStore.getPosition("firstBool").line_);
  53. EXPECT_EQ(234, testStore.getPosition("firstBool").pos_);
  54. EXPECT_EQ("kea.conf", testStore.getPosition("firstBool").file_);
  55. EXPECT_EQ(10, testStore.getPosition("secondBool").line_);
  56. EXPECT_EQ(20, testStore.getPosition("secondBool").pos_);
  57. EXPECT_EQ("keax.conf", testStore.getPosition("secondBool").file_);
  58. // Verify that we can update parameters.
  59. testStore.setParam("firstBool", true, Element::Position("keax.conf", 555, 111));
  60. testStore.setParam("secondBool", false, Element::Position("kea.conf", 1, 3));
  61. EXPECT_TRUE(testStore.getParam("firstBool"));
  62. EXPECT_FALSE(testStore.getParam("secondBool"));
  63. EXPECT_EQ(555, testStore.getPosition("firstBool").line_);
  64. EXPECT_EQ(111, testStore.getPosition("firstBool").pos_);
  65. EXPECT_EQ("keax.conf", testStore.getPosition("firstBool").file_);
  66. EXPECT_EQ(1, testStore.getPosition("secondBool").line_);
  67. EXPECT_EQ(3, testStore.getPosition("secondBool").pos_);
  68. EXPECT_EQ("kea.conf", testStore.getPosition("secondBool").file_);
  69. // Verify that we can delete a parameter and it will no longer be found.
  70. testStore.delParam("firstBool");
  71. EXPECT_THROW(testStore.getParam("firstBool"), isc::dhcp::DhcpConfigError);
  72. // Verify that the "zero" position is returned when parameter doesn't exist.
  73. EXPECT_TRUE(isZeroPosition(testStore, "firstBool"));
  74. // Verify that the delete was safe and the store still operates.
  75. EXPECT_FALSE(testStore.getParam("secondBool"));
  76. EXPECT_EQ(1, testStore.getPosition("secondBool").line_);
  77. EXPECT_EQ(3, testStore.getPosition("secondBool").pos_);
  78. EXPECT_EQ("kea.conf", testStore.getPosition("secondBool").file_);
  79. // Verify that looking for a parameter that never existed throws.
  80. ASSERT_THROW(testStore.getParam("bogusBool"), isc::dhcp::DhcpConfigError);
  81. // Verify that the "zero" position is returned when parameter doesn't exist.
  82. EXPECT_TRUE(isZeroPosition(testStore, "bogusBool"));
  83. // Verify that attempting to delete a parameter that never existed does not throw.
  84. EXPECT_NO_THROW(testStore.delParam("bogusBool"));
  85. // Verify that we can empty the list.
  86. testStore.clear();
  87. EXPECT_THROW(testStore.getParam("secondBool"), isc::dhcp::DhcpConfigError);
  88. // Verify that the "zero" position is returned when parameter doesn't exist.
  89. EXPECT_TRUE(isZeroPosition(testStore, "secondBool"));
  90. }
  91. // This test verifies that Uint32Storage functions properly.
  92. TEST(ValueStorageTest, Uint32Testing) {
  93. Uint32Storage testStore;
  94. uint32_t int_one = 77;
  95. uint32_t int_two = 33;
  96. // Verify that we can add and retrieve parameters.
  97. testStore.setParam("firstInt", int_one, Element::Position("kea.conf", 123, 234));
  98. testStore.setParam("secondInt", int_two, Element::Position("keax.conf", 10, 20));
  99. EXPECT_EQ(testStore.getParam("firstInt"), int_one);
  100. EXPECT_EQ(testStore.getParam("secondInt"), int_two);
  101. EXPECT_EQ(123, testStore.getPosition("firstInt").line_);
  102. EXPECT_EQ(234, testStore.getPosition("firstInt").pos_);
  103. EXPECT_EQ("kea.conf", testStore.getPosition("firstInt").file_);
  104. EXPECT_EQ(10, testStore.getPosition("secondInt").line_);
  105. EXPECT_EQ(20, testStore.getPosition("secondInt").pos_);
  106. EXPECT_EQ("keax.conf", testStore.getPosition("secondInt").file_);
  107. // Verify that we can update parameters.
  108. testStore.setParam("firstInt", --int_one, Element::Position("keax.conf", 555, 111));
  109. testStore.setParam("secondInt", ++int_two, Element::Position("kea.conf", 1, 3));
  110. EXPECT_EQ(testStore.getParam("firstInt"), int_one);
  111. EXPECT_EQ(testStore.getParam("secondInt"), int_two);
  112. EXPECT_EQ(555, testStore.getPosition("firstInt").line_);
  113. EXPECT_EQ(111, testStore.getPosition("firstInt").pos_);
  114. EXPECT_EQ("keax.conf", testStore.getPosition("firstInt").file_);
  115. EXPECT_EQ(1, testStore.getPosition("secondInt").line_);
  116. EXPECT_EQ(3, testStore.getPosition("secondInt").pos_);
  117. EXPECT_EQ("kea.conf", testStore.getPosition("secondInt").file_);
  118. // Verify that we can delete a parameter and it will no longer be found.
  119. testStore.delParam("firstInt");
  120. EXPECT_THROW(testStore.getParam("firstInt"), isc::dhcp::DhcpConfigError);
  121. // Verify that the "zero" position is returned when parameter doesn't exist.
  122. EXPECT_TRUE(isZeroPosition(testStore, "firstInt"));
  123. // Verify that the delete was safe and the store still operates.
  124. EXPECT_EQ(testStore.getParam("secondInt"), int_two);
  125. EXPECT_EQ(1, testStore.getPosition("secondInt").line_);
  126. EXPECT_EQ(3, testStore.getPosition("secondInt").pos_);
  127. EXPECT_EQ("kea.conf", testStore.getPosition("secondInt").file_);
  128. // Verify that looking for a parameter that never existed throws.
  129. ASSERT_THROW(testStore.getParam("bogusInt"), isc::dhcp::DhcpConfigError);
  130. // Verify that attempting to delete a parameter that never existed does not throw.
  131. EXPECT_NO_THROW(testStore.delParam("bogusInt"));
  132. // Verify that the "zero" position is returned when parameter doesn't exist.
  133. EXPECT_TRUE(isZeroPosition(testStore, "bogusInt"));
  134. // Verify that we can empty the list.
  135. testStore.clear();
  136. EXPECT_THROW(testStore.getParam("secondInt"), isc::dhcp::DhcpConfigError);
  137. // Verify that the "zero" position is returned when parameter doesn't exist.
  138. EXPECT_TRUE(isZeroPosition(testStore, "secondInt"));
  139. }
  140. // This test verifies that StringStorage functions properly.
  141. TEST(ValueStorageTest, StringTesting) {
  142. StringStorage testStore;
  143. std::string string_one = "seventy-seven";
  144. std::string string_two = "thirty-three";
  145. // Verify that we can add and retrieve parameters.
  146. testStore.setParam("firstString", string_one,
  147. Element::Position("kea.conf", 123, 234));
  148. testStore.setParam("secondString", string_two,
  149. Element::Position("keax.conf", 10, 20));
  150. EXPECT_EQ(testStore.getParam("firstString"), string_one);
  151. EXPECT_EQ(testStore.getParam("secondString"), string_two);
  152. EXPECT_EQ(123, testStore.getPosition("firstString").line_);
  153. EXPECT_EQ(234, testStore.getPosition("firstString").pos_);
  154. EXPECT_EQ("kea.conf", testStore.getPosition("firstString").file_);
  155. EXPECT_EQ(10, testStore.getPosition("secondString").line_);
  156. EXPECT_EQ(20, testStore.getPosition("secondString").pos_);
  157. EXPECT_EQ("keax.conf", testStore.getPosition("secondString").file_);
  158. // Verify that we can update parameters.
  159. string_one.append("-boo");
  160. string_two.append("-boo");
  161. testStore.setParam("firstString", string_one,
  162. Element::Position("kea.conf", 555, 111));
  163. testStore.setParam("secondString", string_two,
  164. Element::Position("keax.conf", 1, 3));
  165. EXPECT_EQ(testStore.getParam("firstString"), string_one);
  166. EXPECT_EQ(testStore.getParam("secondString"), string_two);
  167. EXPECT_EQ(555, testStore.getPosition("firstString").line_);
  168. EXPECT_EQ(111, testStore.getPosition("firstString").pos_);
  169. EXPECT_EQ("kea.conf", testStore.getPosition("firstString").file_);
  170. EXPECT_EQ(1, testStore.getPosition("secondString").line_);
  171. EXPECT_EQ(3, testStore.getPosition("secondString").pos_);
  172. EXPECT_EQ("keax.conf", testStore.getPosition("secondString").file_);
  173. // Verify that we can delete a parameter and it will no longer be found.
  174. testStore.delParam("firstString");
  175. EXPECT_THROW(testStore.getParam("firstString"), isc::dhcp::DhcpConfigError);
  176. // Verify that the "zero" position is returned when parameter doesn't exist.
  177. EXPECT_TRUE(isZeroPosition(testStore, "firstString"));
  178. // Verify that the delete was safe and the store still operates.
  179. EXPECT_EQ(testStore.getParam("secondString"), string_two);
  180. EXPECT_EQ(1, testStore.getPosition("secondString").line_);
  181. EXPECT_EQ(3, testStore.getPosition("secondString").pos_);
  182. EXPECT_EQ("keax.conf", testStore.getPosition("secondString").file_);
  183. // Verify that looking for a parameter that never existed throws.
  184. ASSERT_THROW(testStore.getParam("bogusString"), isc::dhcp::DhcpConfigError);
  185. // Verify that attempting to delete a parameter that never existed does not throw.
  186. EXPECT_NO_THROW(testStore.delParam("bogusString"));
  187. // Verify that the "zero" position is returned when parameter doesn't exist.
  188. EXPECT_TRUE(isZeroPosition(testStore, "bogusString"));
  189. // Verify that we can empty the list.
  190. testStore.clear();
  191. EXPECT_THROW(testStore.getParam("secondString"), isc::dhcp::DhcpConfigError);
  192. // Verify that the "zero" position is returned when parameter doesn't exist.
  193. EXPECT_TRUE(isZeroPosition(testStore, "secondString"));
  194. }
  195. class CfgMgrTest : public ::testing::Test {
  196. public:
  197. CfgMgrTest() {
  198. // make sure we start with a clean configuration
  199. clear();
  200. }
  201. /// @brief generates interface-id option based on provided text
  202. ///
  203. /// @param text content of the option to be created
  204. ///
  205. /// @return pointer to the option object created
  206. OptionPtr generateInterfaceId(const string& text) {
  207. OptionBuffer buffer(text.begin(), text.end());
  208. return OptionPtr(new Option(Option::V6, D6O_INTERFACE_ID, buffer));
  209. }
  210. ~CfgMgrTest() {
  211. // clean up after the test
  212. clear();
  213. }
  214. void clear() {
  215. CfgMgr::instance().setVerbose(false);
  216. CfgMgr::instance().clear();
  217. }
  218. /// used in client classification (or just empty container for other tests)
  219. isc::dhcp::ClientClasses classify_;
  220. };
  221. // Checks that there is a configuration structure available and that
  222. // it is empty by default.
  223. TEST_F(CfgMgrTest, configuration) {
  224. ConstSrvConfigPtr configuration = CfgMgr::instance().getCurrentCfg();
  225. ASSERT_TRUE(configuration);
  226. EXPECT_TRUE(configuration->getLoggingInfo().empty());
  227. configuration = CfgMgr::instance().getStagingCfg();
  228. ASSERT_TRUE(configuration);
  229. EXPECT_TRUE(configuration->getLoggingInfo().empty());
  230. }
  231. // This test verifies that new DHCPv4 option spaces can be added to
  232. // the configuration manager and that duplicated option space is
  233. // rejected.
  234. TEST_F(CfgMgrTest, optionSpace4) {
  235. CfgMgr& cfg_mgr = CfgMgr::instance();
  236. // Create some option spaces.
  237. OptionSpacePtr space1(new OptionSpace("isc", false));
  238. OptionSpacePtr space2(new OptionSpace("xyz", true));
  239. // Add option spaces with different names and expect they
  240. // are accepted.
  241. ASSERT_NO_THROW(cfg_mgr.addOptionSpace4(space1));
  242. ASSERT_NO_THROW(cfg_mgr.addOptionSpace4(space2));
  243. // Validate that the option spaces have been added correctly.
  244. const OptionSpaceCollection& spaces = cfg_mgr.getOptionSpaces4();
  245. ASSERT_EQ(2, spaces.size());
  246. EXPECT_FALSE(spaces.find("isc") == spaces.end());
  247. EXPECT_FALSE(spaces.find("xyz") == spaces.end());
  248. // Create another option space with the name that duplicates
  249. // the existing option space.
  250. OptionSpacePtr space3(new OptionSpace("isc", true));
  251. // Expect that the duplicate option space is rejected.
  252. ASSERT_THROW(
  253. cfg_mgr.addOptionSpace4(space3), isc::dhcp::InvalidOptionSpace
  254. );
  255. /// @todo decode if a duplicate vendor space is allowed.
  256. }
  257. // This test verifies that new DHCPv6 option spaces can be added to
  258. // the configuration manager and that duplicated option space is
  259. // rejected.
  260. TEST_F(CfgMgrTest, optionSpace6) {
  261. CfgMgr& cfg_mgr = CfgMgr::instance();
  262. // Create some option spaces.
  263. OptionSpacePtr space1(new OptionSpace("isc", false));
  264. OptionSpacePtr space2(new OptionSpace("xyz", true));
  265. // Add option spaces with different names and expect they
  266. // are accepted.
  267. ASSERT_NO_THROW(cfg_mgr.addOptionSpace6(space1));
  268. ASSERT_NO_THROW(cfg_mgr.addOptionSpace6(space2));
  269. // Validate that the option spaces have been added correctly.
  270. const OptionSpaceCollection& spaces = cfg_mgr.getOptionSpaces6();
  271. ASSERT_EQ(2, spaces.size());
  272. EXPECT_FALSE(spaces.find("isc") == spaces.end());
  273. EXPECT_FALSE(spaces.find("xyz") == spaces.end());
  274. // Create another option space with the name that duplicates
  275. // the existing option space.
  276. OptionSpacePtr space3(new OptionSpace("isc", true));
  277. // Expect that the duplicate option space is rejected.
  278. ASSERT_THROW(
  279. cfg_mgr.addOptionSpace6(space3), isc::dhcp::InvalidOptionSpace
  280. );
  281. /// @todo decide if a duplicate vendor space is allowed.
  282. }
  283. // This test verifies that RFC6842 (echo client-id) compatibility may be
  284. // configured.
  285. TEST_F(CfgMgrTest, echoClientId) {
  286. CfgMgr& cfg_mgr = CfgMgr::instance();
  287. // Check that the default is true
  288. EXPECT_TRUE(cfg_mgr.echoClientId());
  289. // Check that it can be modified to false
  290. cfg_mgr.echoClientId(false);
  291. EXPECT_FALSE(cfg_mgr.echoClientId());
  292. // Check that the default value can be restored
  293. cfg_mgr.echoClientId(true);
  294. EXPECT_TRUE(cfg_mgr.echoClientId());
  295. }
  296. // This test checks the D2ClientMgr wrapper methods.
  297. TEST_F(CfgMgrTest, d2ClientConfig) {
  298. // After CfgMgr construction, D2ClientMgr member should be initialized
  299. // with a D2 configuration that is disabled.
  300. // Verify we can Fetch the mgr.
  301. D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
  302. EXPECT_FALSE(d2_mgr.ddnsEnabled());
  303. // Make sure the convenience method fetches the config correctly.
  304. D2ClientConfigPtr original_config = CfgMgr::instance().getD2ClientConfig();
  305. ASSERT_TRUE(original_config);
  306. EXPECT_FALSE(original_config->getEnableUpdates());
  307. // Verify that we cannot set the configuration to an empty pointer.
  308. D2ClientConfigPtr new_cfg;
  309. ASSERT_THROW(CfgMgr::instance().setD2ClientConfig(new_cfg), D2ClientError);
  310. // Create a new, enabled configuration.
  311. ASSERT_NO_THROW(new_cfg.reset(new D2ClientConfig(true,
  312. isc::asiolink::IOAddress("127.0.0.1"), 477,
  313. isc::asiolink::IOAddress("127.0.0.1"), 478,
  314. 1024,
  315. dhcp_ddns::NCR_UDP, dhcp_ddns::FMT_JSON,
  316. true, true, true, true,
  317. "pre-fix", "suf-fix")));
  318. // Verify that we can assign a new, non-empty configuration.
  319. ASSERT_NO_THROW(CfgMgr::instance().setD2ClientConfig(new_cfg));
  320. // Verify that we can fetch the newly assigned configuration.
  321. D2ClientConfigPtr updated_config = CfgMgr::instance().getD2ClientConfig();
  322. ASSERT_TRUE(updated_config);
  323. EXPECT_TRUE(updated_config->getEnableUpdates());
  324. // Make sure convenience method agrees with updated configuration.
  325. EXPECT_TRUE(CfgMgr::instance().ddnsEnabled());
  326. // Make sure the configuration we fetched is the one we assigned,
  327. // and not the original configuration.
  328. EXPECT_EQ(*new_cfg, *updated_config);
  329. EXPECT_NE(*original_config, *updated_config);
  330. }
  331. // This test verifies that the configuration staging, commit and rollback works
  332. // as expected.
  333. TEST_F(CfgMgrTest, staging) {
  334. CfgMgr& cfg_mgr = CfgMgr::instance();
  335. // Initially, the current configuration is a default one. We are going
  336. // to get the current configuration a couple of times and make sure
  337. // that always the same instance is returned.
  338. ConstSrvConfigPtr const_config;
  339. for (int i = 0; i < 5; ++i) {
  340. const_config = cfg_mgr.getCurrentCfg();
  341. ASSERT_TRUE(const_config) << "Returned NULL current configuration"
  342. " for iteration " << i;
  343. EXPECT_EQ(0, const_config->getSequence())
  344. << "Returned invalid sequence number "
  345. << const_config->getSequence() << " for iteration " << i;
  346. }
  347. // Try to get the new staging configuration. When getStagingCfg() is called
  348. // for the first time the new instance of the staging configuration is
  349. // returned. This instance is returned for every call to getStagingCfg()
  350. // until commit is called.
  351. SrvConfigPtr config;
  352. for (int i = 0; i < 5; ++i) {
  353. config = cfg_mgr.getStagingCfg();
  354. ASSERT_TRUE(config) << "Returned NULL staging configuration for"
  355. " iteration " << i;
  356. // The sequence id is 1 for staging because it is ahead of current
  357. // configuration having sequence number 0.
  358. EXPECT_EQ(1, config->getSequence()) << "Returned invalid sequence"
  359. " number " << config->getSequence() << " for iteration " << i;
  360. }
  361. // This should change the staging configuration so as it becomes a current
  362. // one.
  363. cfg_mgr.commit();
  364. const_config = cfg_mgr.getCurrentCfg();
  365. ASSERT_TRUE(const_config);
  366. // Sequence id equal to 1 indicates that the current configuration points
  367. // to the configuration that used to be a staging configuration previously.
  368. EXPECT_EQ(1, const_config->getSequence());
  369. // Create a new staging configuration. It should be assigned a new
  370. // sequence id.
  371. config = cfg_mgr.getStagingCfg();
  372. ASSERT_TRUE(config);
  373. EXPECT_EQ(2, config->getSequence());
  374. // Let's execute commit a couple of times. The first invocation to commit
  375. // changes the configuration having sequence 2 to current configuration.
  376. // Other commits are no-op.
  377. for (int i = 0; i < 5; ++i) {
  378. cfg_mgr.commit();
  379. }
  380. // The current configuration now have sequence number 2.
  381. const_config = cfg_mgr.getCurrentCfg();
  382. ASSERT_TRUE(const_config);
  383. EXPECT_EQ(2, const_config->getSequence());
  384. // Clear configuration along with a history.
  385. cfg_mgr.clear();
  386. // After clearing configuration we should successfully get the
  387. // new staging configuration.
  388. config = cfg_mgr.getStagingCfg();
  389. ASSERT_TRUE(config);
  390. EXPECT_EQ(1, config->getSequence());
  391. // Modify the staging configuration.
  392. config->addLoggingInfo(LoggingInfo());
  393. ASSERT_TRUE(config);
  394. // The modified staging configuration should have one logger configured.
  395. ASSERT_EQ(1, config->getLoggingInfo().size());
  396. // Rollback should remove a staging configuration, including the logger.
  397. ASSERT_NO_THROW(cfg_mgr.rollback());
  398. // Make sure that the logger is not set. This is an indication that the
  399. // rollback worked.
  400. config = cfg_mgr.getStagingCfg();
  401. ASSERT_TRUE(config);
  402. EXPECT_EQ(0, config->getLoggingInfo().size());
  403. }
  404. // This test verifies that it is possible to revert to an old configuration.
  405. TEST_F(CfgMgrTest, revert) {
  406. CfgMgr& cfg_mgr = CfgMgr::instance();
  407. // Let's create 5 unique configurations: differing by a debug level in the
  408. // range of 10 to 14.
  409. for (int i = 0; i < 5; ++i) {
  410. SrvConfigPtr config = cfg_mgr.getStagingCfg();
  411. LoggingInfo logging_info;
  412. logging_info.debuglevel_ = i + 10;
  413. config->addLoggingInfo(logging_info);
  414. cfg_mgr.commit();
  415. }
  416. // Now we have 6 configurations with:
  417. // - debuglevel = 99 (a default one)
  418. // - debuglevel = 10
  419. // - debuglevel = 11
  420. // - debuglevel = 12
  421. // - debuglevel = 13
  422. // - debuglevel = 14 (current)
  423. // Hence, the maximum index of the configuration to revert is 5 (which
  424. // points to the configuration with debuglevel = 99). For the index greater
  425. // than 5 we should get an exception.
  426. ASSERT_THROW(cfg_mgr.revert(6), isc::OutOfRange);
  427. // Value of 0 also doesn't make sense.
  428. ASSERT_THROW(cfg_mgr.revert(0), isc::OutOfRange);
  429. // We should be able to revert to configuration with debuglevel = 10.
  430. ASSERT_NO_THROW(cfg_mgr.revert(4));
  431. // And this configuration should be now the current one and the debuglevel
  432. // of this configuration is 10.
  433. EXPECT_EQ(10, cfg_mgr.getCurrentCfg()->getLoggingInfo()[0].debuglevel_);
  434. EXPECT_NE(cfg_mgr.getCurrentCfg()->getSequence(), 1);
  435. // The new set of configuration is now as follows:
  436. // - debuglevel = 99
  437. // - debuglevel = 10
  438. // - debuglevel = 11
  439. // - debuglevel = 12
  440. // - debuglevel = 13
  441. // - debuglevel = 14
  442. // - debuglevel = 10 (current)
  443. // So, reverting to configuration having index 3 means that the debug level
  444. // of the current configuration will become 12.
  445. ASSERT_NO_THROW(cfg_mgr.revert(3));
  446. EXPECT_EQ(12, cfg_mgr.getCurrentCfg()->getLoggingInfo()[0].debuglevel_);
  447. }
  448. // This test verifies that the verbosity can be set and obtained from the
  449. // configuration manager.
  450. TEST_F(CfgMgrTest, verbosity) {
  451. ASSERT_FALSE(CfgMgr::instance().isVerbose());
  452. CfgMgr::instance().setVerbose(true);
  453. ASSERT_TRUE(CfgMgr::instance().isVerbose());
  454. CfgMgr::instance().setVerbose(false);
  455. EXPECT_FALSE(CfgMgr::instance().isVerbose());
  456. }
  457. // This test verifies that once the configuration is committed, statistics
  458. // are updated appropriately.
  459. TEST_F(CfgMgrTest, commitStats4) {
  460. CfgMgr& cfg_mgr = CfgMgr::instance();
  461. StatsMgr& stats_mgr = StatsMgr::instance();
  462. // Let's prepare the "old" configuration: a subnet with id 123
  463. // and pretend there were addresses assigned, so statistics are non-zero.
  464. Subnet4Ptr subnet1(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3, 123));
  465. CfgSubnets4Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
  466. subnets->add(subnet1);
  467. cfg_mgr.commit();
  468. stats_mgr.addValue("subnet[123].total-addresses", static_cast<int64_t>(256));
  469. stats_mgr.setValue("subnet[123].assigned-addresses", static_cast<int64_t>(150));
  470. // Now, let's change the configuration to something new.
  471. // There's a subnet 192.1.2.0/24 with ID=42
  472. Subnet4Ptr subnet2(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3, 42));
  473. // Let's make a pool with 128 addresses available.
  474. PoolPtr pool(new Pool4(IOAddress("192.1.2.0"), 25)); // 128 addrs
  475. subnet2->addPool(pool);
  476. subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
  477. subnets->add(subnet2);
  478. // Let's commit it
  479. cfg_mgr.commit();
  480. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-addresses"));
  481. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-addresses"));
  482. ObservationPtr total_addrs;
  483. EXPECT_NO_THROW(total_addrs = stats_mgr.getObservation("subnet[42].total-addresses"));
  484. ASSERT_TRUE(total_addrs);
  485. EXPECT_EQ(128, total_addrs->getInteger().first);
  486. }
  487. // This test verifies that once the configuration is cleared, the statistics
  488. // are removed.
  489. TEST_F(CfgMgrTest, clearStats4) {
  490. CfgMgr& cfg_mgr = CfgMgr::instance();
  491. StatsMgr& stats_mgr = StatsMgr::instance();
  492. // Let's prepare the "old" configuration: a subnet with id 123
  493. // and pretend there were addresses assigned, so statistics are non-zero.
  494. Subnet4Ptr subnet1(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3, 123));
  495. CfgSubnets4Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
  496. subnets->add(subnet1);
  497. cfg_mgr.commit();
  498. stats_mgr.addValue("subnet[123].total-addresses", static_cast<int64_t>(256));
  499. stats_mgr.setValue("subnet[123].assigned-addresses", static_cast<int64_t>(150));
  500. // The stats should be there.
  501. EXPECT_TRUE(stats_mgr.getObservation("subnet[123].total-addresses"));
  502. EXPECT_TRUE(stats_mgr.getObservation("subnet[123].assigned-addresses"));
  503. // Let's remove all configurations
  504. cfg_mgr.clear();
  505. // The stats should not be there anymore.
  506. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-addresses"));
  507. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-addresses"));
  508. }
  509. // This test verifies that once the configuration is committed, statistics
  510. // are updated appropriately.
  511. TEST_F(CfgMgrTest, commitStats6) {
  512. CfgMgr& cfg_mgr = CfgMgr::instance();
  513. StatsMgr& stats_mgr = StatsMgr::instance();
  514. // Let's prepare the "old" configuration: a subnet with id 123
  515. // and pretend there were addresses assigned, so statistics are non-zero.
  516. Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4, 123));
  517. CfgSubnets6Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets6();
  518. subnets->add(subnet1);
  519. cfg_mgr.commit();
  520. stats_mgr.addValue("subnet[123].total-nas", static_cast<int64_t>(256));
  521. stats_mgr.setValue("subnet[123].assigned-nas", static_cast<int64_t>(150));
  522. stats_mgr.addValue("subnet[123].total-pds", static_cast<int64_t>(256));
  523. stats_mgr.setValue("subnet[123].assigned-pds", static_cast<int64_t>(150));
  524. // Now, let's change the configuration to something new.
  525. // There's a subnet 2001:db8:2::/48 with ID=42
  526. Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4, 42));
  527. // Let's make pools with 128 addresses and 65536 prefixes available.
  528. PoolPtr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:2::"), 121)); // 128 addrs
  529. PoolPtr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:3::"), 96, 112)); // 65536 prefixes
  530. subnet2->addPool(pool1);
  531. subnet2->addPool(pool2);
  532. subnets = cfg_mgr.getStagingCfg()->getCfgSubnets6();
  533. subnets->add(subnet2);
  534. // Let's commit it
  535. cfg_mgr.commit();
  536. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-nas"));
  537. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-nas"));
  538. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-pds"));
  539. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-pds"));
  540. ObservationPtr total_addrs;
  541. EXPECT_NO_THROW(total_addrs = stats_mgr.getObservation("subnet[42].total-nas"));
  542. ASSERT_TRUE(total_addrs);
  543. EXPECT_EQ(128, total_addrs->getInteger().first);
  544. EXPECT_NO_THROW(total_addrs = stats_mgr.getObservation("subnet[42].total-pds"));
  545. ASSERT_TRUE(total_addrs);
  546. EXPECT_EQ(65536, total_addrs->getInteger().first);
  547. }
  548. // This test verifies that once the configuration is cleared, the v6 statistics
  549. // are removed.
  550. TEST_F(CfgMgrTest, clearStats6) {
  551. CfgMgr& cfg_mgr = CfgMgr::instance();
  552. StatsMgr& stats_mgr = StatsMgr::instance();
  553. // Let's prepare the "old" configuration: a subnet with id 123
  554. // and pretend there were addresses assigned, so statistics are non-zero.
  555. Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4, 123));
  556. CfgSubnets6Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets6();
  557. subnets->add(subnet1);
  558. cfg_mgr.commit();
  559. stats_mgr.addValue("subnet[123].total-nas", static_cast<int64_t>(256));
  560. stats_mgr.setValue("subnet[123].assigned-nas", static_cast<int64_t>(150));
  561. stats_mgr.addValue("subnet[123].total-pds", static_cast<int64_t>(256));
  562. stats_mgr.setValue("subnet[123].assigned-pds", static_cast<int64_t>(150));
  563. // The stats should be there.
  564. EXPECT_TRUE(stats_mgr.getObservation("subnet[123].total-nas"));
  565. EXPECT_TRUE(stats_mgr.getObservation("subnet[123].assigned-nas"));
  566. EXPECT_TRUE(stats_mgr.getObservation("subnet[123].total-pds"));
  567. EXPECT_TRUE(stats_mgr.getObservation("subnet[123].assigned-pds"));
  568. // Let's remove all configurations
  569. cfg_mgr.clear();
  570. // The stats should not be there anymore.
  571. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-nas"));
  572. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-nas"));
  573. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-pds"));
  574. EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-pds"));
  575. }
  576. /// @todo Add unit-tests for testing:
  577. /// - addActiveIface() with invalid interface name
  578. /// - addActiveIface() with the same interface twice
  579. /// - addActiveIface() with a bogus address
  580. ///
  581. /// This is somewhat tricky. Care should be taken here, because it is rather
  582. /// difficult to decide if interface name is valid or not. Some servers, e.g.
  583. /// dibbler, allow to specify interface names that are not currently present in
  584. /// the system. The server accepts them, but upon discovering that they are
  585. /// yet available (for different definitions of not being available), adds
  586. /// the to to-be-activated list.
  587. ///
  588. /// Cases covered by dibbler are:
  589. /// - missing interface (e.g. PPP connection that is not established yet)
  590. /// - downed interface (no link local address, no way to open sockets)
  591. /// - up, but not running interface (wifi up, but not associated)
  592. /// - tentative addresses (interface up and running, but DAD procedure is
  593. /// still in progress)
  594. /// - weird interfaces without link-local addresses (don't ask, 6rd tunnels
  595. /// look weird to me as well)
  596. // No specific tests for getSubnet6. That method (2 overloaded versions) is tested
  597. // in Dhcpv6SrvTest.selectSubnetAddr and Dhcpv6SrvTest.selectSubnetIface
  598. // (see src/bin/dhcp6/tests/dhcp6_srv_unittest.cc)
  599. } // end of anonymous namespace