sqlite3_accessor_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 <datasrc/sqlite3_accessor.h>
  15. #include <datasrc/data_source.h>
  16. #include <dns/rrclass.h>
  17. #include <gtest/gtest.h>
  18. #include <boost/scoped_ptr.hpp>
  19. using namespace isc::datasrc;
  20. using isc::data::ConstElementPtr;
  21. using isc::data::Element;
  22. using isc::dns::RRClass;
  23. using isc::dns::Name;
  24. namespace {
  25. // Some test data
  26. std::string SQLITE_DBFILE_EXAMPLE = TEST_DATA_DIR "/test.sqlite3";
  27. std::string SQLITE_DBFILE_EXAMPLE2 = TEST_DATA_DIR "/example2.com.sqlite3";
  28. std::string SQLITE_DBNAME_EXAMPLE2 = "sqlite3_example2.com.sqlite3";
  29. std::string SQLITE_DBFILE_EXAMPLE_ROOT = TEST_DATA_DIR "/test-root.sqlite3";
  30. std::string SQLITE_DBNAME_EXAMPLE_ROOT = "sqlite3_test-root.sqlite3";
  31. std::string SQLITE_DBFILE_BROKENDB = TEST_DATA_DIR "/brokendb.sqlite3";
  32. std::string SQLITE_DBFILE_MEMORY = ":memory:";
  33. // The following file must be non existent and must be non"creatable";
  34. // the sqlite3 library will try to create a new DB file if it doesn't exist,
  35. // so to test a failure case the create operation should also fail.
  36. // The "nodir", a non existent directory, is inserted for this purpose.
  37. std::string SQLITE_DBFILE_NOTEXIST = TEST_DATA_DIR "/nodir/notexist";
  38. // Opening works (the content is tested in different tests)
  39. TEST(SQLite3Open, common) {
  40. EXPECT_NO_THROW(SQLite3Database db(SQLITE_DBFILE_EXAMPLE,
  41. RRClass::IN()));
  42. }
  43. // The file can't be opened
  44. TEST(SQLite3Open, notExist) {
  45. EXPECT_THROW(SQLite3Database db(SQLITE_DBFILE_NOTEXIST,
  46. RRClass::IN()), SQLite3Error);
  47. }
  48. // It rejects broken DB
  49. TEST(SQLite3Open, brokenDB) {
  50. EXPECT_THROW(SQLite3Database db(SQLITE_DBFILE_BROKENDB,
  51. RRClass::IN()), SQLite3Error);
  52. }
  53. // Test we can create the schema on the fly
  54. TEST(SQLite3Open, memoryDB) {
  55. EXPECT_NO_THROW(SQLite3Database db(SQLITE_DBFILE_MEMORY,
  56. RRClass::IN()));
  57. }
  58. // Test fixture for querying the db
  59. class SQLite3Access : public ::testing::Test {
  60. public:
  61. SQLite3Access() {
  62. initAccessor(SQLITE_DBFILE_EXAMPLE, RRClass::IN());
  63. }
  64. // So it can be re-created with different data
  65. void initAccessor(const std::string& filename, const RRClass& rrclass) {
  66. db.reset(new SQLite3Database(filename, rrclass));
  67. }
  68. // The tested db
  69. boost::shared_ptr<SQLite3Database> db;
  70. };
  71. // This zone exists in the data, so it should be found
  72. TEST_F(SQLite3Access, getZone) {
  73. std::pair<bool, int> result(db->getZone(Name("example.com")));
  74. EXPECT_TRUE(result.first);
  75. EXPECT_EQ(1, result.second);
  76. }
  77. // But it should find only the zone, nothing below it
  78. TEST_F(SQLite3Access, subZone) {
  79. EXPECT_FALSE(db->getZone(Name("sub.example.com")).first);
  80. }
  81. // This zone is not there at all
  82. TEST_F(SQLite3Access, noZone) {
  83. EXPECT_FALSE(db->getZone(Name("example.org")).first);
  84. }
  85. // This zone is there, but in different class
  86. TEST_F(SQLite3Access, noClass) {
  87. initAccessor(SQLITE_DBFILE_EXAMPLE, RRClass::CH());
  88. EXPECT_FALSE(db->getZone(Name("example.com")).first);
  89. }
  90. // This tests the iterator context
  91. TEST_F(SQLite3Access, iterator) {
  92. // Our test zone is conveniently small, but not empty
  93. initAccessor(SQLITE_DBFILE_EXAMPLE2, RRClass::IN());
  94. // Get the iterator context
  95. DatabaseAccessor::IteratorContextPtr
  96. context(db->getAllRecords(1));
  97. ASSERT_NE(DatabaseAccessor::IteratorContextPtr(),
  98. context);
  99. const size_t size(5);
  100. std::string data[size];
  101. // Get and check the first and only record
  102. EXPECT_TRUE(context->getNext(data));
  103. EXPECT_EQ("example2.com.", data[4]);
  104. EXPECT_EQ("SOA", data[0]);
  105. EXPECT_EQ("master.example2.com. admin.example2.com. "
  106. "1234 3600 1800 2419200 7200", data[3]);
  107. EXPECT_EQ("3600", data[1]);
  108. // Check there's no other
  109. EXPECT_FALSE(context->getNext(data));
  110. }
  111. TEST_F(SQLite3Access, iteratorColumnCount) {
  112. // Our test zone is conveniently small, but not empty
  113. initAccessor(SQLITE_DBFILE_EXAMPLE2, RRClass::IN());
  114. // Get the iterator context
  115. DatabaseAccessor::IteratorContextPtr
  116. context(db->getAllRecords(1));
  117. ASSERT_NE(DatabaseAccessor::IteratorContextPtr(),
  118. context);
  119. std::string data[DatabaseAccessor::COLUMN_COUNT];
  120. EXPECT_NO_THROW(context->getNext(data));
  121. }
  122. TEST(SQLite3Open, getDBNameExample2) {
  123. SQLite3Database db(SQLITE_DBFILE_EXAMPLE2, RRClass::IN());
  124. EXPECT_EQ(SQLITE_DBNAME_EXAMPLE2, db.getDBName());
  125. }
  126. TEST(SQLite3Open, getDBNameExampleROOT) {
  127. SQLite3Database db(SQLITE_DBFILE_EXAMPLE_ROOT, RRClass::IN());
  128. EXPECT_EQ(SQLITE_DBNAME_EXAMPLE_ROOT, db.getDBName());
  129. }
  130. // Simple function to cound the number of records for
  131. // any name
  132. void
  133. checkRecordRow(const std::string columns[],
  134. const std::string& field0,
  135. const std::string& field1,
  136. const std::string& field2,
  137. const std::string& field3,
  138. const std::string& field4)
  139. {
  140. EXPECT_EQ(field0, columns[0]);
  141. EXPECT_EQ(field1, columns[1]);
  142. EXPECT_EQ(field2, columns[2]);
  143. EXPECT_EQ(field3, columns[3]);
  144. EXPECT_EQ(field4, columns[4]);
  145. }
  146. TEST_F(SQLite3Access, getRecords) {
  147. const std::pair<bool, int> zone_info(db->getZone(Name("example.com")));
  148. ASSERT_TRUE(zone_info.first);
  149. const int zone_id = zone_info.second;
  150. ASSERT_EQ(1, zone_id);
  151. const size_t column_count = DatabaseAccessor::COLUMN_COUNT;
  152. std::string columns[column_count];
  153. DatabaseAccessor::IteratorContextPtr
  154. context(db->getRecords(Name("foo.bar"), 1));
  155. ASSERT_NE(DatabaseAccessor::IteratorContextPtr(),
  156. context);
  157. EXPECT_FALSE(context->getNext(columns));
  158. checkRecordRow(columns, "", "", "", "", "");
  159. // now try some real searches
  160. context = db->getRecords(Name("foo.example.com."), zone_id);
  161. ASSERT_TRUE(context->getNext(columns));
  162. checkRecordRow(columns, "CNAME", "3600", "",
  163. "cnametest.example.org.", "");
  164. ASSERT_TRUE(context->getNext(columns));
  165. checkRecordRow(columns, "RRSIG", "3600", "CNAME",
  166. "CNAME 5 3 3600 20100322084538 20100220084538 33495 "
  167. "example.com. FAKEFAKEFAKEFAKE", "");
  168. ASSERT_TRUE(context->getNext(columns));
  169. checkRecordRow(columns, "NSEC", "7200", "",
  170. "mail.example.com. CNAME RRSIG NSEC", "");
  171. ASSERT_TRUE(context->getNext(columns));
  172. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  173. "NSEC 5 3 7200 20100322084538 20100220084538 33495 "
  174. "example.com. FAKEFAKEFAKEFAKE", "");
  175. EXPECT_FALSE(context->getNext(columns));
  176. // with no more records, the array should not have been modified
  177. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  178. "NSEC 5 3 7200 20100322084538 20100220084538 33495 "
  179. "example.com. FAKEFAKEFAKEFAKE", "");
  180. context = db->getRecords(Name("example.com."), zone_id);
  181. ASSERT_TRUE(context->getNext(columns));
  182. checkRecordRow(columns, "SOA", "3600", "",
  183. "master.example.com. admin.example.com. "
  184. "1234 3600 1800 2419200 7200", "");
  185. ASSERT_TRUE(context->getNext(columns));
  186. checkRecordRow(columns, "RRSIG", "3600", "SOA",
  187. "SOA 5 2 3600 20100322084538 20100220084538 "
  188. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  189. ASSERT_TRUE(context->getNext(columns));
  190. checkRecordRow(columns, "NS", "1200", "", "dns01.example.com.", "");
  191. ASSERT_TRUE(context->getNext(columns));
  192. checkRecordRow(columns, "NS", "3600", "", "dns02.example.com.", "");
  193. ASSERT_TRUE(context->getNext(columns));
  194. checkRecordRow(columns, "NS", "1800", "", "dns03.example.com.", "");
  195. ASSERT_TRUE(context->getNext(columns));
  196. checkRecordRow(columns, "RRSIG", "3600", "NS",
  197. "NS 5 2 3600 20100322084538 20100220084538 "
  198. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  199. ASSERT_TRUE(context->getNext(columns));
  200. checkRecordRow(columns, "MX", "3600", "", "10 mail.example.com.", "");
  201. ASSERT_TRUE(context->getNext(columns));
  202. checkRecordRow(columns, "MX", "3600", "",
  203. "20 mail.subzone.example.com.", "");
  204. ASSERT_TRUE(context->getNext(columns));
  205. checkRecordRow(columns, "RRSIG", "3600", "MX",
  206. "MX 5 2 3600 20100322084538 20100220084538 "
  207. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  208. ASSERT_TRUE(context->getNext(columns));
  209. checkRecordRow(columns, "NSEC", "7200", "",
  210. "cname-ext.example.com. NS SOA MX RRSIG NSEC DNSKEY", "");
  211. ASSERT_TRUE(context->getNext(columns));
  212. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  213. "NSEC 5 2 7200 20100322084538 20100220084538 "
  214. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  215. ASSERT_TRUE(context->getNext(columns));
  216. checkRecordRow(columns, "DNSKEY", "3600", "",
  217. "256 3 5 AwEAAcOUBllYc1hf7ND9uDy+Yz1BF3sI0m4q NGV7W"
  218. "cTD0WEiuV7IjXgHE36fCmS9QsUxSSOV o1I/FMxI2PJVqTYHkX"
  219. "FBS7AzLGsQYMU7UjBZ SotBJ6Imt5pXMu+lEDNy8TOUzG3xm7g"
  220. "0qcbW YF6qCEfvZoBtAqi5Rk7Mlrqs8agxYyMx", "");
  221. ASSERT_TRUE(context->getNext(columns));
  222. checkRecordRow(columns, "DNSKEY", "3600", "",
  223. "257 3 5 AwEAAe5WFbxdCPq2jZrZhlMj7oJdff3W7syJ tbvzg"
  224. "62tRx0gkoCDoBI9DPjlOQG0UAbj+xUV 4HQZJStJaZ+fHU5AwV"
  225. "NT+bBZdtV+NujSikhd THb4FYLg2b3Cx9NyJvAVukHp/91HnWu"
  226. "G4T36 CzAFrfPwsHIrBz9BsaIQ21VRkcmj7DswfI/i DGd8j6b"
  227. "qiODyNZYQ+ZrLmF0KIJ2yPN3iO6Zq 23TaOrVTjB7d1a/h31OD"
  228. "fiHAxFHrkY3t3D5J R9Nsl/7fdRmSznwtcSDgLXBoFEYmw6p86"
  229. "Acv RyoYNcL1SXjaKVLG5jyU3UR+LcGZT5t/0xGf oIK/aKwEN"
  230. "rsjcKZZj660b1M=", "");
  231. ASSERT_TRUE(context->getNext(columns));
  232. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  233. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  234. "4456 example.com. FAKEFAKEFAKEFAKE", "");
  235. ASSERT_TRUE(context->getNext(columns));
  236. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  237. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  238. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  239. EXPECT_FALSE(context->getNext(columns));
  240. // getnextrecord returning false should mean array is not altered
  241. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  242. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  243. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  244. }
  245. } // end anonymous namespace