cache_config_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright (C) 2013 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/cache_config.h>
  15. #include <datasrc/tests/mock_client.h>
  16. #include <cc/data.h>
  17. #include <dns/name.h>
  18. #include <gtest/gtest.h>
  19. #include <iterator> // for std::distance
  20. using namespace isc::datasrc;
  21. using namespace isc::data;
  22. using namespace isc::dns;
  23. using isc::datasrc::unittest::MockDataSourceClient;
  24. using isc::datasrc::internal::CacheConfig;
  25. using isc::datasrc::internal::CacheConfigError;
  26. namespace {
  27. const char* zones[] = {
  28. "example.org.",
  29. "example.com.",
  30. NULL
  31. };
  32. class CacheConfigTest : public ::testing::Test {
  33. protected:
  34. CacheConfigTest() :
  35. mock_client_(zones),
  36. master_config_(Element::fromJSON(
  37. "{\"cache-enable\": true,"
  38. " \"params\": "
  39. " {\".\": \"" TEST_DATA_DIR "/root.zone\"}"
  40. "}")),
  41. mock_config_(Element::fromJSON("{\"cache-enable\": true,"
  42. " \"cache-zones\": [\".\"]}"))
  43. {}
  44. MockDataSourceClient mock_client_;
  45. const ConstElementPtr master_config_; // valid config for MasterFiles
  46. const ConstElementPtr mock_config_; // valid config for MasterFiles
  47. };
  48. size_t
  49. countZones(const CacheConfig& cache_config) {
  50. return (std::distance(cache_config.begin(), cache_config.end()));
  51. }
  52. TEST_F(CacheConfigTest, constructMasterFiles) {
  53. // A simple case: configuring a MasterFiles table with a single zone
  54. const CacheConfig cache_conf("MasterFiles", 0, *master_config_, true);
  55. EXPECT_EQ(1, countZones(cache_conf));
  56. // With multiple zones. Note that the constructor doesn't check if the
  57. // file exists, so they can be anything.
  58. const ConstElementPtr config_elem_multi(
  59. Element::fromJSON("{\"cache-enable\": true,"
  60. " \"params\": "
  61. "{\"example.com\": \"file1\","
  62. " \"example.org\": \"file2\","
  63. " \"example.info\": \"file3\"}"
  64. "}"));
  65. const CacheConfig cache_conf2("MasterFiles", 0, *config_elem_multi, true);
  66. EXPECT_EQ(3, countZones(cache_conf2));
  67. // A bit unusual, but acceptable case: empty parameters, so no zones.
  68. const CacheConfig cache_conf3("MasterFiles", 0,
  69. *Element::fromJSON("{\"cache-enable\": true,"
  70. " \"params\": {}}"),
  71. true);
  72. EXPECT_EQ(0, countZones(cache_conf3));
  73. }
  74. TEST_F(CacheConfigTest, badConstructMasterFiles) {
  75. // no "params"
  76. EXPECT_THROW(CacheConfig("MasterFiles", 0,
  77. *Element::fromJSON("{\"cache-enable\": true}"),
  78. true),
  79. isc::data::TypeError);
  80. // no "cache-enable"
  81. EXPECT_THROW(CacheConfig("MasterFiles", 0,
  82. *Element::fromJSON("{\"params\": {}}"), true),
  83. CacheConfigError);
  84. // cache disabled for MasterFiles
  85. EXPECT_THROW(CacheConfig("MasterFiles", 0,
  86. *Element::fromJSON("{\"cache-enable\": false,"
  87. " \"params\": {}}"), true),
  88. CacheConfigError);
  89. // cache enabled but not "allowed"
  90. EXPECT_THROW(CacheConfig("MasterFiles", 0,
  91. *Element::fromJSON("{\"cache-enable\": false,"
  92. " \"params\": {}}"), false),
  93. CacheConfigError);
  94. // type error for cache-enable
  95. EXPECT_THROW(CacheConfig("MasterFiles", 0,
  96. *Element::fromJSON("{\"cache-enable\": 1,"
  97. " \"params\": {}}"), true),
  98. isc::data::TypeError);
  99. // "params" is not a map
  100. EXPECT_THROW(CacheConfig("MasterFiles", 0,
  101. *Element::fromJSON("{\"cache-enable\": true,"
  102. " \"params\": []}"), true),
  103. isc::data::TypeError);
  104. // bogus zone name
  105. const ConstElementPtr bad_config(Element::fromJSON(
  106. "{\"cache-enable\": true,"
  107. " \"params\": "
  108. "{\"bad..name\": \"file1\"}}"));
  109. EXPECT_THROW(CacheConfig("MasterFiles", 0, *bad_config, true),
  110. isc::dns::EmptyLabel);
  111. // file name is not a string
  112. const ConstElementPtr bad_config2(Element::fromJSON(
  113. "{\"cache-enable\": true,"
  114. " \"params\": {\".\": 1}}"));
  115. EXPECT_THROW(CacheConfig("MasterFiles", 0, *bad_config2, true),
  116. isc::data::TypeError);
  117. // Specify data source client (must be null for MasterFiles)
  118. EXPECT_THROW(CacheConfig("MasterFiles", &mock_client_,
  119. *Element::fromJSON("{\"cache-enable\": true,"
  120. " \"params\": {}}"), true),
  121. isc::InvalidParameter);
  122. }
  123. TEST_F(CacheConfigTest, constructWithMock) {
  124. // Performing equivalent set of tests as constructMasterFiles
  125. // Configure with a single zone.
  126. const CacheConfig cache_conf("mock", &mock_client_, *mock_config_, true);
  127. EXPECT_EQ(1, countZones(cache_conf));
  128. EXPECT_TRUE(cache_conf.isEnabled());
  129. // Configure with multiple zones.
  130. const ConstElementPtr config_elem_multi(
  131. Element::fromJSON("{\"cache-enable\": true,"
  132. " \"cache-zones\": "
  133. "[\"example.com\", \"example.org\",\"example.info\"]"
  134. "}"));
  135. const CacheConfig cache_conf2("mock", &mock_client_, *config_elem_multi,
  136. true);
  137. EXPECT_EQ(3, countZones(cache_conf2));
  138. // Empty
  139. const CacheConfig cache_conf3(
  140. "mock", &mock_client_,
  141. *Element::fromJSON("{\"cache-enable\": true,"
  142. " \"cache-zones\": []}"), true);
  143. EXPECT_EQ(0, countZones(cache_conf3));
  144. // disabled. value of cache-zones are ignored.
  145. const ConstElementPtr config_elem_disabled(
  146. Element::fromJSON("{\"cache-enable\": false,"
  147. " \"cache-zones\": [\"example.com\"]}"));
  148. EXPECT_FALSE(CacheConfig("mock", &mock_client_, *config_elem_disabled,
  149. true).isEnabled());
  150. // enabled but not "allowed". same effect.
  151. EXPECT_FALSE(CacheConfig("mock", &mock_client_,
  152. *Element::fromJSON("{\"cache-enable\": true,"
  153. " \"cache-zones\": []}"),
  154. false).isEnabled());
  155. }
  156. TEST_F(CacheConfigTest, badConstructWithMock) {
  157. // no "cache-zones" (may become valid in future, but for now "notimp")
  158. EXPECT_THROW(CacheConfig("mock", &mock_client_,
  159. *Element::fromJSON("{\"cache-enable\": true}"),
  160. true),
  161. isc::NotImplemented);
  162. // "cache-zones" is not a list
  163. EXPECT_THROW(CacheConfig("mock", &mock_client_,
  164. *Element::fromJSON("{\"cache-enable\": true,"
  165. " \"cache-zones\": {}}"),
  166. true),
  167. isc::data::TypeError);
  168. // "cache-zone" entry is not a string
  169. EXPECT_THROW(CacheConfig("mock", &mock_client_,
  170. *Element::fromJSON("{\"cache-enable\": true,"
  171. " \"cache-zones\": [1]}"),
  172. true),
  173. isc::data::TypeError);
  174. // bogus zone name
  175. const ConstElementPtr bad_config(Element::fromJSON(
  176. "{\"cache-enable\": true,"
  177. " \"cache-zones\": [\"bad..\"]}"));
  178. EXPECT_THROW(CacheConfig("mock", &mock_client_, *bad_config, true),
  179. isc::dns::EmptyLabel);
  180. // duplicate zone name (note that comparison is case insensitive)
  181. const ConstElementPtr dup_config(Element::fromJSON(
  182. "{\"cache-enable\": true,"
  183. " \"cache-zones\": "
  184. " [\"example\", \"EXAMPLE\"]}"));
  185. EXPECT_THROW(CacheConfig("mock", &mock_client_, *dup_config, true),
  186. CacheConfigError);
  187. // datasrc is null
  188. EXPECT_THROW(CacheConfig("mock", 0, *mock_config_, true),
  189. isc::InvalidParameter);
  190. }
  191. TEST_F(CacheConfigTest, getSegmentType) {
  192. // Default type
  193. EXPECT_EQ("local",
  194. CacheConfig("MasterFiles", 0,
  195. *master_config_, true).getSegmentType());
  196. // If we explicitly configure it, that value should be used.
  197. ConstElementPtr config(Element::fromJSON("{\"cache-enable\": true,"
  198. " \"cache-type\": \"mapped\","
  199. " \"params\": {}}" ));
  200. EXPECT_EQ("mapped",
  201. CacheConfig("MasterFiles", 0, *config, true).getSegmentType());
  202. // Wrong types: should be rejected at construction time
  203. ConstElementPtr badconfig(Element::fromJSON("{\"cache-enable\": true,"
  204. " \"cache-type\": 1,"
  205. " \"params\": {}}"));
  206. EXPECT_THROW(CacheConfig("MasterFiles", 0, *badconfig, true),
  207. isc::data::TypeError);
  208. // Bad value: should be rejected at construction time
  209. ConstElementPtr badconfig2(Element::fromJSON("{\"cache-enable\": true,"
  210. " \"cache-type\": \"bogus\","
  211. " \"params\": {}}"));
  212. EXPECT_THROW(CacheConfig("MasterFiles", 0, *badconfig2, true),
  213. isc::datasrc::internal::CacheConfigError);
  214. }
  215. }