factory_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Copyright (C) 2011 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 <boost/scoped_ptr.hpp>
  15. #include <datasrc/datasrc_config.h>
  16. #include <datasrc/factory.h>
  17. #include <datasrc/data_source.h>
  18. #include <datasrc/sqlite3_accessor.h>
  19. #include <dns/rrclass.h>
  20. #include <cc/data.h>
  21. #include <gtest/gtest.h>
  22. using namespace isc::datasrc;
  23. using namespace isc::data;
  24. std::string SQLITE_DBFILE_EXAMPLE_ORG = TEST_DATA_DIR "/example.org.sqlite3";
  25. const std::string STATIC_DS_FILE = TEST_DATA_DIR "/static.zone";
  26. const std::string ROOT_ZONE_FILE = TEST_DATA_DIR "/root.zone";
  27. namespace {
  28. // note this helper only checks the error that is received up to the length
  29. // of the expected string. It will always pass if you give it an empty
  30. // expected_error
  31. void
  32. pathtestHelper(const std::string& file, const std::string& expected_error) {
  33. std::string error;
  34. try {
  35. DataSourceClientContainer(file, ElementPtr());
  36. } catch (const DataSourceLibraryError& dsle) {
  37. error = dsle.what();
  38. }
  39. ASSERT_LT(expected_error.size(), error.size());
  40. EXPECT_EQ(expected_error, error.substr(0, expected_error.size()));
  41. }
  42. TEST(FactoryTest, paths) {
  43. // Test whether the paths are made absolute if they are not,
  44. // by inspecting the error that is raised when they are wrong
  45. const std::string error("dlopen failed for ");
  46. // With the current implementation, we can safely assume this has
  47. // been set for this test (as the loader would otherwise also fail
  48. // unless the loadable backend library happens to be installed)
  49. const std::string builddir(getenv("B10_FROM_BUILD"));
  50. // Absolute and ending with .so should have no change
  51. pathtestHelper("/no_such_file.so", error + "/no_such_file.so");
  52. // If no ending in .so, it should get _ds.so
  53. pathtestHelper("/no_such_file", error + "/no_such_file_ds.so");
  54. // If not starting with /, path should be added. For this test that
  55. // means the build directory as set in B10_FROM_BUILD
  56. pathtestHelper("no_such_file.so", error + builddir +
  57. "/src/lib/datasrc/.libs/no_such_file.so");
  58. pathtestHelper("no_such_file", error + builddir +
  59. "/src/lib/datasrc/.libs/no_such_file_ds.so");
  60. // Some tests with '.so' in the name itself
  61. pathtestHelper("no_such_file.so.something", error + builddir +
  62. "/src/lib/datasrc/.libs/no_such_file.so.something_ds.so");
  63. pathtestHelper("/no_such_file.so.something", error +
  64. "/no_such_file.so.something_ds.so");
  65. pathtestHelper("/no_such_file.so.something.so", error +
  66. "/no_such_file.so.something.so");
  67. pathtestHelper("/no_such_file.so.so", error +
  68. "/no_such_file.so.so");
  69. pathtestHelper("no_such_file.so.something", error + builddir +
  70. "/src/lib/datasrc/.libs/no_such_file.so.something_ds.so");
  71. // Temporarily unset B10_FROM_BUILD to see that BACKEND_LIBRARY_PATH
  72. // is used
  73. unsetenv("B10_FROM_BUILD");
  74. pathtestHelper("no_such_file.so", error + BACKEND_LIBRARY_PATH +
  75. "no_such_file.so");
  76. // Put it back just in case
  77. setenv("B10_FROM_BUILD", builddir.c_str(), 1);
  78. // Test some bad input values
  79. ASSERT_THROW(DataSourceClientContainer("", ElementPtr()),
  80. DataSourceLibraryError);
  81. ASSERT_THROW(DataSourceClientContainer(".so", ElementPtr()),
  82. DataSourceLibraryError);
  83. }
  84. TEST(FactoryTest, sqlite3ClientBadConfig) {
  85. // We start out by building the configuration data bit by bit,
  86. // testing each form of 'bad config', until we have a good one.
  87. // Then we do some very basic operation on the client (detailed
  88. // tests are left to the implementation-specific backends)
  89. ElementPtr config;
  90. ASSERT_THROW(DataSourceClientContainer("sqlite3", config),
  91. DataSourceError);
  92. config = Element::create("asdf");
  93. ASSERT_THROW(DataSourceClientContainer("sqlite3", config),
  94. DataSourceError);
  95. config = Element::createMap();
  96. ASSERT_THROW(DataSourceClientContainer("sqlite3", config),
  97. DataSourceError);
  98. config->set("class", ElementPtr());
  99. ASSERT_THROW(DataSourceClientContainer("sqlite3", config),
  100. DataSourceError);
  101. config->set("class", Element::create(1));
  102. ASSERT_THROW(DataSourceClientContainer("sqlite3", config),
  103. DataSourceError);
  104. config->set("class", Element::create("FOO"));
  105. ASSERT_THROW(DataSourceClientContainer("sqlite3", config),
  106. DataSourceError);
  107. config->set("class", Element::create("IN"));
  108. ASSERT_THROW(DataSourceClientContainer("sqlite3", config),
  109. DataSourceError);
  110. config->set("database_file", ElementPtr());
  111. ASSERT_THROW(DataSourceClientContainer("sqlite3", config),
  112. DataSourceError);
  113. config->set("database_file", Element::create(1));
  114. ASSERT_THROW(DataSourceClientContainer("sqlite3", config),
  115. DataSourceError);
  116. config->set("database_file", Element::create("/foo/bar/doesnotexist"));
  117. ASSERT_THROW(DataSourceClientContainer("sqlite3", config),
  118. DataSourceError);
  119. config->set("database_file", Element::create(SQLITE_DBFILE_EXAMPLE_ORG));
  120. DataSourceClientContainer dsc("sqlite3", config);
  121. DataSourceClient::FindResult result1(
  122. dsc.getInstance().findZone(isc::dns::Name("example.org.")));
  123. ASSERT_EQ(result::SUCCESS, result1.code);
  124. DataSourceClient::FindResult result2(
  125. dsc.getInstance().findZone(isc::dns::Name("no.such.zone.")));
  126. ASSERT_EQ(result::NOTFOUND, result2.code);
  127. ZoneIteratorPtr iterator(dsc.getInstance().getIterator(
  128. isc::dns::Name("example.org.")));
  129. ZoneUpdaterPtr updater(dsc.getInstance().getUpdater(
  130. isc::dns::Name("example.org."), false));
  131. }
  132. TEST(FactoryTest, memoryClient) {
  133. // We start out by building the configuration data bit by bit,
  134. // testing each form of 'bad config', until we have a good one.
  135. // Then we do some very basic operation on the client (detailed
  136. // tests are left to the implementation-specific backends)
  137. ElementPtr config;
  138. ASSERT_THROW(DataSourceClientContainer client("memory", config),
  139. DataSourceError);
  140. config = Element::create("asdf");
  141. ASSERT_THROW(DataSourceClientContainer("memory", config),
  142. DataSourceError);
  143. config = Element::createMap();
  144. ASSERT_THROW(DataSourceClientContainer("memory", config),
  145. DataSourceError);
  146. config->set("type", ElementPtr());
  147. ASSERT_THROW(DataSourceClientContainer("memory", config),
  148. DataSourceError);
  149. config->set("type", Element::create(1));
  150. ASSERT_THROW(DataSourceClientContainer("memory", config),
  151. DataSourceError);
  152. config->set("type", Element::create("FOO"));
  153. ASSERT_THROW(DataSourceClientContainer("memory", config),
  154. DataSourceError);
  155. config->set("type", Element::create("memory"));
  156. // no config at all should result in a default empty memory client
  157. ASSERT_NO_THROW(DataSourceClientContainer("memory", config));
  158. config->set("class", ElementPtr());
  159. ASSERT_THROW(DataSourceClientContainer("memory", config),
  160. DataSourceError);
  161. config->set("class", Element::create(1));
  162. ASSERT_THROW(DataSourceClientContainer("memory", config),
  163. DataSourceError);
  164. config->set("class", Element::create("FOO"));
  165. ASSERT_THROW(DataSourceClientContainer("memory", config),
  166. DataSourceError);
  167. config->set("class", Element::create("IN"));
  168. ASSERT_NO_THROW(DataSourceClientContainer("memory", config));
  169. config->set("zones", ElementPtr());
  170. ASSERT_THROW(DataSourceClientContainer("memory", config),
  171. DataSourceError);
  172. config->set("zones", Element::create(1));
  173. ASSERT_THROW(DataSourceClientContainer("memory", config),
  174. DataSourceError);
  175. config->set("zones", Element::createList());
  176. DataSourceClientContainer dsc("memory", config);
  177. // Once it is able to load some zones, we should add a few tests
  178. // here to see that it does.
  179. DataSourceClient::FindResult result(
  180. dsc.getInstance().findZone(isc::dns::Name("no.such.zone.")));
  181. ASSERT_EQ(result::NOTFOUND, result.code);
  182. ASSERT_THROW(dsc.getInstance().getIterator(isc::dns::Name("example.org.")),
  183. DataSourceError);
  184. ASSERT_THROW(dsc.getInstance().getUpdater(isc::dns::Name("no.such.zone."),
  185. false), isc::NotImplemented);
  186. }
  187. TEST(FactoryTest, badType) {
  188. ASSERT_THROW(DataSourceClientContainer("foo", ElementPtr()),
  189. DataSourceError);
  190. }
  191. // Check the static data source can be loaded.
  192. TEST(FactoryTest, staticDS) {
  193. // The only configuration is the file to load.
  194. const ConstElementPtr config(new StringElement(STATIC_DS_FILE));
  195. // Get the data source
  196. DataSourceClientContainer dsc("static", config);
  197. // And try getting something out to see if it really works.
  198. DataSourceClient::FindResult
  199. result(dsc.getInstance().findZone(isc::dns::Name("BIND")));
  200. ASSERT_EQ(result::SUCCESS, result.code);
  201. EXPECT_EQ(isc::dns::Name("BIND"), result.zone_finder->getOrigin());
  202. EXPECT_EQ(isc::dns::RRClass::CH(), result.zone_finder->getClass());
  203. const isc::dns::ConstRRsetPtr
  204. version(result.zone_finder->find(isc::dns::Name("VERSION.BIND"),
  205. isc::dns::RRType::TXT())->rrset);
  206. ASSERT_NE(isc::dns::ConstRRsetPtr(), version);
  207. EXPECT_EQ(isc::dns::Name("VERSION.BIND"), version->getName());
  208. EXPECT_EQ(isc::dns::RRClass::CH(), version->getClass());
  209. EXPECT_EQ(isc::dns::RRType::TXT(), version->getType());
  210. }
  211. // Check that file not containing BIND./CH is rejected
  212. //
  213. // FIXME: This test is disabled because the InMemoryZoneFinder::load does
  214. // not check if the data loaded correspond with the origin. The static
  215. // factory is not the place to fix that.
  216. TEST(FactoryTest, DISABLED_staticDSBadFile) {
  217. // The only configuration is the file to load.
  218. const ConstElementPtr config(new StringElement(STATIC_DS_FILE));
  219. // See it does not want the file
  220. EXPECT_THROW(DataSourceClientContainer("static", config), DataSourceError);
  221. }
  222. // Check that some bad configs are rejected
  223. TEST(FactoryTest, staticDSBadConfig) {
  224. const char* configs[] = {
  225. // The file does not exist
  226. "\"/does/not/exist\"",
  227. // Bad types
  228. "null",
  229. "42",
  230. "{}",
  231. "[]",
  232. "true",
  233. NULL
  234. };
  235. for (const char** config(configs); *config; ++config) {
  236. SCOPED_TRACE(*config);
  237. EXPECT_THROW(DataSourceClientContainer("static",
  238. Element::fromJSON(*config)),
  239. DataSourceError);
  240. }
  241. }
  242. } // end anonymous namespace