sqlite3_accessor_unittest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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(Name("example2.com"), 1));
  97. ASSERT_NE(DatabaseAccessor::IteratorContextPtr(),
  98. context);
  99. size_t size(5);
  100. std::string data[size];
  101. // Get and check the first and only record
  102. EXPECT_TRUE(context->getNext(data, size));
  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, size));
  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(Name("example2.com"), 1));
  117. ASSERT_NE(DatabaseAccessor::IteratorContextPtr(),
  118. context);
  119. EXPECT_THROW(context->getNext(NULL, 0), DataSourceError);
  120. std::string data[6];
  121. EXPECT_THROW(context->getNext(data, 4), DataSourceError);
  122. EXPECT_THROW(context->getNext(data, 6), DataSourceError);
  123. EXPECT_NO_THROW(context->getNext(data, 5));
  124. }
  125. TEST(SQLite3Open, getDBNameExample2) {
  126. SQLite3Database db(SQLITE_DBFILE_EXAMPLE2, RRClass::IN());
  127. EXPECT_EQ(SQLITE_DBNAME_EXAMPLE2, db.getDBName());
  128. }
  129. TEST(SQLite3Open, getDBNameExampleROOT) {
  130. SQLite3Database db(SQLITE_DBFILE_EXAMPLE_ROOT, RRClass::IN());
  131. EXPECT_EQ(SQLITE_DBNAME_EXAMPLE_ROOT, db.getDBName());
  132. }
  133. // Simple function to cound the number of records for
  134. // any name
  135. void
  136. checkRecordRow(const std::string columns[],
  137. const std::string& field0,
  138. const std::string& field1,
  139. const std::string& field2,
  140. const std::string& field3,
  141. const std::string& field4)
  142. {
  143. EXPECT_EQ(field0, columns[0]);
  144. EXPECT_EQ(field1, columns[1]);
  145. EXPECT_EQ(field2, columns[2]);
  146. EXPECT_EQ(field3, columns[3]);
  147. EXPECT_EQ(field4, columns[4]);
  148. }
  149. TEST_F(SQLite3Access, getRecords) {
  150. const std::pair<bool, int> zone_info(db->getZone(Name("example.com")));
  151. ASSERT_TRUE(zone_info.first);
  152. const int zone_id = zone_info.second;
  153. ASSERT_EQ(1, zone_id);
  154. const size_t column_count = DatabaseAccessor::COLUMN_COUNT;
  155. std::string columns[column_count];
  156. // without search, getNext() should return false
  157. EXPECT_FALSE(db->getNextRecord(columns, column_count));
  158. checkRecordRow(columns, "", "", "", "", "");
  159. db->searchForRecords(zone_id, "foo.bar.");
  160. EXPECT_FALSE(db->getNextRecord(columns, column_count));
  161. checkRecordRow(columns, "", "", "", "", "");
  162. db->searchForRecords(zone_id, "");
  163. EXPECT_FALSE(db->getNextRecord(columns, column_count));
  164. checkRecordRow(columns, "", "", "", "", "");
  165. // Should error on a bad number of columns
  166. EXPECT_THROW(db->getNextRecord(columns, 4), DataSourceError);
  167. EXPECT_THROW(db->getNextRecord(columns, 6), DataSourceError);
  168. // now try some real searches
  169. db->searchForRecords(zone_id, "foo.example.com.");
  170. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  171. checkRecordRow(columns, "CNAME", "3600", "",
  172. "cnametest.example.org.", "foo.example.com.");
  173. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  174. checkRecordRow(columns, "RRSIG", "3600", "CNAME",
  175. "CNAME 5 3 3600 20100322084538 20100220084538 33495 "
  176. "example.com. FAKEFAKEFAKEFAKE", "foo.example.com.");
  177. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  178. checkRecordRow(columns, "NSEC", "7200", "",
  179. "mail.example.com. CNAME RRSIG NSEC", "foo.example.com.");
  180. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  181. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  182. "NSEC 5 3 7200 20100322084538 20100220084538 33495 "
  183. "example.com. FAKEFAKEFAKEFAKE", "foo.example.com.");
  184. EXPECT_FALSE(db->getNextRecord(columns, column_count));
  185. // with no more records, the array should not have been modified
  186. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  187. "NSEC 5 3 7200 20100322084538 20100220084538 33495 "
  188. "example.com. FAKEFAKEFAKEFAKE", "foo.example.com.");
  189. db->searchForRecords(zone_id, "example.com.");
  190. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  191. checkRecordRow(columns, "SOA", "3600", "",
  192. "master.example.com. admin.example.com. "
  193. "1234 3600 1800 2419200 7200", "example.com.");
  194. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  195. checkRecordRow(columns, "RRSIG", "3600", "SOA",
  196. "SOA 5 2 3600 20100322084538 20100220084538 "
  197. "33495 example.com. FAKEFAKEFAKEFAKE", "example.com.");
  198. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  199. checkRecordRow(columns, "NS", "1200", "", "dns01.example.com.",
  200. "example.com.");
  201. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  202. checkRecordRow(columns, "NS", "3600", "", "dns02.example.com.",
  203. "example.com.");
  204. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  205. checkRecordRow(columns, "NS", "1800", "", "dns03.example.com.",
  206. "example.com.");
  207. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  208. checkRecordRow(columns, "RRSIG", "3600", "NS",
  209. "NS 5 2 3600 20100322084538 20100220084538 "
  210. "33495 example.com. FAKEFAKEFAKEFAKE",
  211. "example.com.");
  212. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  213. checkRecordRow(columns, "MX", "3600", "", "10 mail.example.com.",
  214. "example.com.");
  215. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  216. checkRecordRow(columns, "MX", "3600", "",
  217. "20 mail.subzone.example.com.", "example.com.");
  218. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  219. checkRecordRow(columns, "RRSIG", "3600", "MX",
  220. "MX 5 2 3600 20100322084538 20100220084538 "
  221. "33495 example.com. FAKEFAKEFAKEFAKE", "example.com.");
  222. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  223. checkRecordRow(columns, "NSEC", "7200", "",
  224. "cname-ext.example.com. NS SOA MX RRSIG NSEC DNSKEY",
  225. "example.com.");
  226. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  227. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  228. "NSEC 5 2 7200 20100322084538 20100220084538 "
  229. "33495 example.com. FAKEFAKEFAKEFAKE", "example.com.");
  230. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  231. checkRecordRow(columns, "DNSKEY", "3600", "",
  232. "256 3 5 AwEAAcOUBllYc1hf7ND9uDy+Yz1BF3sI0m4q NGV7W"
  233. "cTD0WEiuV7IjXgHE36fCmS9QsUxSSOV o1I/FMxI2PJVqTYHkX"
  234. "FBS7AzLGsQYMU7UjBZ SotBJ6Imt5pXMu+lEDNy8TOUzG3xm7g"
  235. "0qcbW YF6qCEfvZoBtAqi5Rk7Mlrqs8agxYyMx", "example.com.");
  236. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  237. checkRecordRow(columns, "DNSKEY", "3600", "",
  238. "257 3 5 AwEAAe5WFbxdCPq2jZrZhlMj7oJdff3W7syJ tbvzg"
  239. "62tRx0gkoCDoBI9DPjlOQG0UAbj+xUV 4HQZJStJaZ+fHU5AwV"
  240. "NT+bBZdtV+NujSikhd THb4FYLg2b3Cx9NyJvAVukHp/91HnWu"
  241. "G4T36 CzAFrfPwsHIrBz9BsaIQ21VRkcmj7DswfI/i DGd8j6b"
  242. "qiODyNZYQ+ZrLmF0KIJ2yPN3iO6Zq 23TaOrVTjB7d1a/h31OD"
  243. "fiHAxFHrkY3t3D5J R9Nsl/7fdRmSznwtcSDgLXBoFEYmw6p86"
  244. "Acv RyoYNcL1SXjaKVLG5jyU3UR+LcGZT5t/0xGf oIK/aKwEN"
  245. "rsjcKZZj660b1M=", "example.com.");
  246. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  247. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  248. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  249. "4456 example.com. FAKEFAKEFAKEFAKE", "example.com.");
  250. ASSERT_TRUE(db->getNextRecord(columns, column_count));
  251. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  252. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  253. "33495 example.com. FAKEFAKEFAKEFAKE", "example.com.");
  254. EXPECT_FALSE(db->getNextRecord(columns, column_count));
  255. // getnextrecord returning false should mean array is not altered
  256. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  257. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  258. "33495 example.com. FAKEFAKEFAKEFAKE", "example.com.");
  259. }
  260. } // end anonymous namespace