sqlite3_accessor_unittest.cc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  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 <algorithm>
  15. #include <vector>
  16. #include <datasrc/sqlite3_accessor.h>
  17. #include <datasrc/data_source.h>
  18. #include <dns/rrclass.h>
  19. #include <gtest/gtest.h>
  20. #include <boost/scoped_ptr.hpp>
  21. #include <fstream>
  22. #include <sqlite3.h>
  23. using namespace std;
  24. using namespace isc::datasrc;
  25. using boost::shared_ptr;
  26. using isc::data::ConstElementPtr;
  27. using isc::data::Element;
  28. using isc::dns::RRClass;
  29. using isc::dns::Name;
  30. namespace {
  31. // Some test data
  32. std::string SQLITE_DBFILE_EXAMPLE = TEST_DATA_DIR "/test.sqlite3";
  33. std::string SQLITE_DBFILE_EXAMPLE2 = TEST_DATA_DIR "/example2.com.sqlite3";
  34. std::string SQLITE_DBNAME_EXAMPLE2 = "sqlite3_example2.com.sqlite3";
  35. std::string SQLITE_DBFILE_EXAMPLE_ROOT = TEST_DATA_DIR "/test-root.sqlite3";
  36. std::string SQLITE_DBNAME_EXAMPLE_ROOT = "sqlite3_test-root.sqlite3";
  37. std::string SQLITE_DBFILE_BROKENDB = TEST_DATA_DIR "/brokendb.sqlite3";
  38. std::string SQLITE_DBFILE_MEMORY = ":memory:";
  39. std::string SQLITE_DBFILE_EXAMPLE_ORG = TEST_DATA_DIR "/example.org.sqlite3";
  40. // The following file must be non existent and must be non"creatable";
  41. // the sqlite3 library will try to create a new DB file if it doesn't exist,
  42. // so to test a failure case the create operation should also fail.
  43. // The "nodir", a non existent directory, is inserted for this purpose.
  44. std::string SQLITE_DBFILE_NOTEXIST = TEST_DATA_DIR "/nodir/notexist";
  45. // new db file, we don't need this to be a std::string, and given the
  46. // raw calls we use it in a const char* is more convenient
  47. const char* SQLITE_NEW_DBFILE = TEST_DATA_BUILDDIR "/newdb.sqlite3";
  48. // Opening works (the content is tested in different tests)
  49. TEST(SQLite3Open, common) {
  50. EXPECT_NO_THROW(SQLite3Accessor accessor(SQLITE_DBFILE_EXAMPLE, "IN"));
  51. }
  52. // The file can't be opened
  53. TEST(SQLite3Open, notExist) {
  54. EXPECT_THROW(SQLite3Accessor accessor(SQLITE_DBFILE_NOTEXIST, "IN"),
  55. SQLite3Error);
  56. }
  57. // It rejects broken DB
  58. TEST(SQLite3Open, brokenDB) {
  59. EXPECT_THROW(SQLite3Accessor accessor(SQLITE_DBFILE_BROKENDB, "IN"),
  60. SQLite3Error);
  61. }
  62. // Test we can create the schema on the fly
  63. TEST(SQLite3Open, memoryDB) {
  64. EXPECT_NO_THROW(SQLite3Accessor accessor(SQLITE_DBFILE_MEMORY, "IN"));
  65. }
  66. // Test fixture for querying the db
  67. class SQLite3AccessorTest : public ::testing::Test {
  68. public:
  69. SQLite3AccessorTest() {
  70. initAccessor(SQLITE_DBFILE_EXAMPLE, "IN");
  71. }
  72. // So it can be re-created with different data
  73. void initAccessor(const std::string& filename, const string& rrclass) {
  74. accessor.reset(new SQLite3Accessor(filename, rrclass));
  75. }
  76. // The tested accessor
  77. boost::shared_ptr<SQLite3Accessor> accessor;
  78. };
  79. // This zone exists in the data, so it should be found
  80. TEST_F(SQLite3AccessorTest, getZone) {
  81. std::pair<bool, int> result(accessor->getZone("example.com."));
  82. EXPECT_TRUE(result.first);
  83. EXPECT_EQ(1, result.second);
  84. }
  85. // But it should find only the zone, nothing below it
  86. TEST_F(SQLite3AccessorTest, subZone) {
  87. EXPECT_FALSE(accessor->getZone("sub.example.com.").first);
  88. }
  89. // This zone is not there at all
  90. TEST_F(SQLite3AccessorTest, noZone) {
  91. EXPECT_FALSE(accessor->getZone("example.org.").first);
  92. }
  93. // This zone is there, but in different class
  94. TEST_F(SQLite3AccessorTest, noClass) {
  95. initAccessor(SQLITE_DBFILE_EXAMPLE, "CH");
  96. EXPECT_FALSE(accessor->getZone("example.com.").first);
  97. }
  98. // This tests the iterator context
  99. TEST_F(SQLite3AccessorTest, iterator) {
  100. // Our test zone is conveniently small, but not empty
  101. initAccessor(SQLITE_DBFILE_EXAMPLE_ORG, "IN");
  102. const std::pair<bool, int> zone_info(accessor->getZone("example.org."));
  103. ASSERT_TRUE(zone_info.first);
  104. // Get the iterator context
  105. DatabaseAccessor::IteratorContextPtr
  106. context(accessor->getAllRecords(zone_info.second));
  107. ASSERT_NE(DatabaseAccessor::IteratorContextPtr(), context);
  108. std::string data[DatabaseAccessor::COLUMN_COUNT];
  109. // Get and check the first and only record
  110. EXPECT_TRUE(context->getNext(data));
  111. EXPECT_EQ("DNAME", data[DatabaseAccessor::TYPE_COLUMN]);
  112. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  113. EXPECT_EQ("dname.example.info.", data[DatabaseAccessor::RDATA_COLUMN]);
  114. EXPECT_EQ("dname.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  115. EXPECT_TRUE(context->getNext(data));
  116. EXPECT_EQ("DNAME", data[DatabaseAccessor::TYPE_COLUMN]);
  117. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  118. EXPECT_EQ("dname2.example.info.", data[DatabaseAccessor::RDATA_COLUMN]);
  119. EXPECT_EQ("dname2.foo.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  120. EXPECT_TRUE(context->getNext(data));
  121. EXPECT_EQ("MX", data[DatabaseAccessor::TYPE_COLUMN]);
  122. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  123. EXPECT_EQ("10 mail.example.org.", data[DatabaseAccessor::RDATA_COLUMN]);
  124. EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  125. EXPECT_TRUE(context->getNext(data));
  126. EXPECT_EQ("NS", data[DatabaseAccessor::TYPE_COLUMN]);
  127. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  128. EXPECT_EQ("ns1.example.org.", data[DatabaseAccessor::RDATA_COLUMN]);
  129. EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  130. EXPECT_TRUE(context->getNext(data));
  131. EXPECT_EQ("NS", data[DatabaseAccessor::TYPE_COLUMN]);
  132. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  133. EXPECT_EQ("ns2.example.org.", data[DatabaseAccessor::RDATA_COLUMN]);
  134. EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  135. EXPECT_TRUE(context->getNext(data));
  136. EXPECT_EQ("NS", data[DatabaseAccessor::TYPE_COLUMN]);
  137. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  138. EXPECT_EQ("ns3.example.org.", data[DatabaseAccessor::RDATA_COLUMN]);
  139. EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  140. EXPECT_TRUE(context->getNext(data));
  141. EXPECT_EQ("SOA", data[DatabaseAccessor::TYPE_COLUMN]);
  142. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  143. EXPECT_EQ("ns1.example.org. admin.example.org. "
  144. "1234 3600 1800 2419200 7200",
  145. data[DatabaseAccessor::RDATA_COLUMN]);
  146. EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  147. EXPECT_TRUE(context->getNext(data));
  148. EXPECT_EQ("A", data[DatabaseAccessor::TYPE_COLUMN]);
  149. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  150. EXPECT_EQ("192.0.2.10", data[DatabaseAccessor::RDATA_COLUMN]);
  151. EXPECT_EQ("mail.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  152. EXPECT_TRUE(context->getNext(data));
  153. EXPECT_EQ("A", data[DatabaseAccessor::TYPE_COLUMN]);
  154. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  155. EXPECT_EQ("192.0.2.101", data[DatabaseAccessor::RDATA_COLUMN]);
  156. EXPECT_EQ("ns.sub.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  157. EXPECT_TRUE(context->getNext(data));
  158. EXPECT_EQ("NS", data[DatabaseAccessor::TYPE_COLUMN]);
  159. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  160. EXPECT_EQ("ns.sub.example.org.", data[DatabaseAccessor::RDATA_COLUMN]);
  161. EXPECT_EQ("sub.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  162. EXPECT_TRUE(context->getNext(data));
  163. EXPECT_EQ("A", data[DatabaseAccessor::TYPE_COLUMN]);
  164. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  165. EXPECT_EQ("192.0.2.1", data[DatabaseAccessor::RDATA_COLUMN]);
  166. EXPECT_EQ("www.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  167. // Check there's no other
  168. EXPECT_FALSE(context->getNext(data));
  169. // And make sure calling it again won't cause problems.
  170. EXPECT_FALSE(context->getNext(data));
  171. }
  172. TEST(SQLite3Open, getDBNameExample2) {
  173. SQLite3Accessor accessor(SQLITE_DBFILE_EXAMPLE2, "IN");
  174. EXPECT_EQ(SQLITE_DBNAME_EXAMPLE2, accessor.getDBName());
  175. }
  176. TEST(SQLite3Open, getDBNameExampleROOT) {
  177. SQLite3Accessor accessor(SQLITE_DBFILE_EXAMPLE_ROOT, "IN");
  178. EXPECT_EQ(SQLITE_DBNAME_EXAMPLE_ROOT, accessor.getDBName());
  179. }
  180. // Simple function to cound the number of records for
  181. // any name
  182. void
  183. checkRecordRow(const std::string columns[],
  184. const std::string& field0,
  185. const std::string& field1,
  186. const std::string& field2,
  187. const std::string& field3,
  188. const std::string& field4)
  189. {
  190. EXPECT_EQ(field0, columns[DatabaseAccessor::TYPE_COLUMN]);
  191. EXPECT_EQ(field1, columns[DatabaseAccessor::TTL_COLUMN]);
  192. EXPECT_EQ(field2, columns[DatabaseAccessor::SIGTYPE_COLUMN]);
  193. EXPECT_EQ(field3, columns[DatabaseAccessor::RDATA_COLUMN]);
  194. EXPECT_EQ(field4, columns[DatabaseAccessor::NAME_COLUMN]);
  195. }
  196. TEST_F(SQLite3AccessorTest, getRecords) {
  197. const std::pair<bool, int> zone_info(accessor->getZone("example.com."));
  198. ASSERT_TRUE(zone_info.first);
  199. const int zone_id = zone_info.second;
  200. ASSERT_EQ(1, zone_id);
  201. std::string columns[DatabaseAccessor::COLUMN_COUNT];
  202. DatabaseAccessor::IteratorContextPtr
  203. context(accessor->getRecords("foo.bar", 1));
  204. ASSERT_NE(DatabaseAccessor::IteratorContextPtr(),
  205. context);
  206. EXPECT_FALSE(context->getNext(columns));
  207. checkRecordRow(columns, "", "", "", "", "");
  208. // now try some real searches
  209. context = accessor->getRecords("foo.example.com.", zone_id);
  210. ASSERT_TRUE(context->getNext(columns));
  211. checkRecordRow(columns, "CNAME", "3600", "",
  212. "cnametest.example.org.", "");
  213. ASSERT_TRUE(context->getNext(columns));
  214. checkRecordRow(columns, "RRSIG", "3600", "CNAME",
  215. "CNAME 5 3 3600 20100322084538 20100220084538 33495 "
  216. "example.com. FAKEFAKEFAKEFAKE", "");
  217. ASSERT_TRUE(context->getNext(columns));
  218. checkRecordRow(columns, "NSEC", "7200", "",
  219. "mail.example.com. CNAME RRSIG NSEC", "");
  220. ASSERT_TRUE(context->getNext(columns));
  221. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  222. "NSEC 5 3 7200 20100322084538 20100220084538 33495 "
  223. "example.com. FAKEFAKEFAKEFAKE", "");
  224. EXPECT_FALSE(context->getNext(columns));
  225. // with no more records, the array should not have been modified
  226. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  227. "NSEC 5 3 7200 20100322084538 20100220084538 33495 "
  228. "example.com. FAKEFAKEFAKEFAKE", "");
  229. context = accessor->getRecords("example.com.", zone_id);
  230. ASSERT_TRUE(context->getNext(columns));
  231. checkRecordRow(columns, "SOA", "3600", "",
  232. "master.example.com. admin.example.com. "
  233. "1234 3600 1800 2419200 7200", "");
  234. ASSERT_TRUE(context->getNext(columns));
  235. checkRecordRow(columns, "RRSIG", "3600", "SOA",
  236. "SOA 5 2 3600 20100322084538 20100220084538 "
  237. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  238. ASSERT_TRUE(context->getNext(columns));
  239. checkRecordRow(columns, "NS", "1200", "", "dns01.example.com.", "");
  240. ASSERT_TRUE(context->getNext(columns));
  241. checkRecordRow(columns, "NS", "3600", "", "dns02.example.com.", "");
  242. ASSERT_TRUE(context->getNext(columns));
  243. checkRecordRow(columns, "NS", "1800", "", "dns03.example.com.", "");
  244. ASSERT_TRUE(context->getNext(columns));
  245. checkRecordRow(columns, "RRSIG", "3600", "NS",
  246. "NS 5 2 3600 20100322084538 20100220084538 "
  247. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  248. ASSERT_TRUE(context->getNext(columns));
  249. checkRecordRow(columns, "MX", "3600", "", "10 mail.example.com.", "");
  250. ASSERT_TRUE(context->getNext(columns));
  251. checkRecordRow(columns, "MX", "3600", "",
  252. "20 mail.subzone.example.com.", "");
  253. ASSERT_TRUE(context->getNext(columns));
  254. checkRecordRow(columns, "RRSIG", "3600", "MX",
  255. "MX 5 2 3600 20100322084538 20100220084538 "
  256. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  257. ASSERT_TRUE(context->getNext(columns));
  258. checkRecordRow(columns, "NSEC", "7200", "",
  259. "cname-ext.example.com. NS SOA MX RRSIG NSEC DNSKEY", "");
  260. ASSERT_TRUE(context->getNext(columns));
  261. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  262. "NSEC 5 2 7200 20100322084538 20100220084538 "
  263. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  264. ASSERT_TRUE(context->getNext(columns));
  265. checkRecordRow(columns, "DNSKEY", "3600", "",
  266. "256 3 5 AwEAAcOUBllYc1hf7ND9uDy+Yz1BF3sI0m4q NGV7W"
  267. "cTD0WEiuV7IjXgHE36fCmS9QsUxSSOV o1I/FMxI2PJVqTYHkX"
  268. "FBS7AzLGsQYMU7UjBZ SotBJ6Imt5pXMu+lEDNy8TOUzG3xm7g"
  269. "0qcbW YF6qCEfvZoBtAqi5Rk7Mlrqs8agxYyMx", "");
  270. ASSERT_TRUE(context->getNext(columns));
  271. checkRecordRow(columns, "DNSKEY", "3600", "",
  272. "257 3 5 AwEAAe5WFbxdCPq2jZrZhlMj7oJdff3W7syJ tbvzg"
  273. "62tRx0gkoCDoBI9DPjlOQG0UAbj+xUV 4HQZJStJaZ+fHU5AwV"
  274. "NT+bBZdtV+NujSikhd THb4FYLg2b3Cx9NyJvAVukHp/91HnWu"
  275. "G4T36 CzAFrfPwsHIrBz9BsaIQ21VRkcmj7DswfI/i DGd8j6b"
  276. "qiODyNZYQ+ZrLmF0KIJ2yPN3iO6Zq 23TaOrVTjB7d1a/h31OD"
  277. "fiHAxFHrkY3t3D5J R9Nsl/7fdRmSznwtcSDgLXBoFEYmw6p86"
  278. "Acv RyoYNcL1SXjaKVLG5jyU3UR+LcGZT5t/0xGf oIK/aKwEN"
  279. "rsjcKZZj660b1M=", "");
  280. ASSERT_TRUE(context->getNext(columns));
  281. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  282. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  283. "4456 example.com. FAKEFAKEFAKEFAKE", "");
  284. ASSERT_TRUE(context->getNext(columns));
  285. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  286. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  287. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  288. EXPECT_FALSE(context->getNext(columns));
  289. // getnextrecord returning false should mean array is not altered
  290. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  291. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  292. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  293. // check that another getNext does not cause problems
  294. EXPECT_FALSE(context->getNext(columns));
  295. // Try searching for subdomain
  296. // There's foo.bar.example.com in the data
  297. context = accessor->getRecords("bar.example.com.", zone_id, true);
  298. ASSERT_TRUE(context->getNext(columns));
  299. checkRecordRow(columns, "A", "3600", "", "192.0.2.1", "");
  300. EXPECT_FALSE(context->getNext(columns));
  301. // But we shouldn't match mix.example.com here
  302. context = accessor->getRecords("ix.example.com.", zone_id, true);
  303. EXPECT_FALSE(context->getNext(columns));
  304. }
  305. TEST_F(SQLite3AccessorTest, findPrevious) {
  306. EXPECT_EQ("dns01.example.com.",
  307. accessor->findPreviousName(1, "com.example.dns02."));
  308. // A name that doesn't exist
  309. EXPECT_EQ("dns01.example.com.",
  310. accessor->findPreviousName(1, "com.example.dns01x."));
  311. // Largest name
  312. EXPECT_EQ("www.example.com.",
  313. accessor->findPreviousName(1, "com.example.wwww"));
  314. // Out of zone after the last name
  315. EXPECT_EQ("www.example.com.",
  316. accessor->findPreviousName(1, "org.example."));
  317. // Case insensitive?
  318. EXPECT_EQ("dns01.example.com.",
  319. accessor->findPreviousName(1, "com.exaMple.DNS02."));
  320. // A name that doesn't exist
  321. EXPECT_EQ("dns01.example.com.",
  322. accessor->findPreviousName(1, "com.exaMple.DNS01X."));
  323. // The DB contains foo.bar.example.com., which would be in between
  324. // these two names. However, that one does not have an NSEC record,
  325. // which is how this database recognizes glue data, so it should
  326. // be skipped.
  327. EXPECT_EQ("example.com.",
  328. accessor->findPreviousName(1, "com.example.cname-ext."));
  329. // Throw when we are before the origin
  330. EXPECT_THROW(accessor->findPreviousName(1, "com.example."),
  331. isc::NotImplemented);
  332. EXPECT_THROW(accessor->findPreviousName(1, "a.example."),
  333. isc::NotImplemented);
  334. }
  335. TEST_F(SQLite3AccessorTest, findPreviousNoData) {
  336. // This one doesn't hold any NSEC records, so it shouldn't work
  337. // The underlying DB/data don't support DNSSEC, so it's not implemented
  338. // (does it make sense? Or different exception here?)
  339. EXPECT_THROW(accessor->findPreviousName(3, "com.example.sql2.www."),
  340. isc::NotImplemented);
  341. }
  342. // Test fixture for creating a db that automatically deletes it before start,
  343. // and when done
  344. class SQLite3Create : public ::testing::Test {
  345. public:
  346. SQLite3Create() {
  347. remove(SQLITE_NEW_DBFILE);
  348. }
  349. ~SQLite3Create() {
  350. remove(SQLITE_NEW_DBFILE);
  351. }
  352. };
  353. bool isReadable(const char* filename) {
  354. return (std::ifstream(filename).is_open());
  355. }
  356. TEST_F(SQLite3Create, creationtest) {
  357. ASSERT_FALSE(isReadable(SQLITE_NEW_DBFILE));
  358. // Should simply be created
  359. SQLite3Accessor accessor(SQLITE_NEW_DBFILE, "IN");
  360. ASSERT_TRUE(isReadable(SQLITE_NEW_DBFILE));
  361. }
  362. TEST_F(SQLite3Create, emptytest) {
  363. ASSERT_FALSE(isReadable(SQLITE_NEW_DBFILE));
  364. // open one manualle
  365. sqlite3* db;
  366. ASSERT_EQ(SQLITE_OK, sqlite3_open(SQLITE_NEW_DBFILE, &db));
  367. // empty, but not locked, so creating it now should work
  368. SQLite3Accessor accessor2(SQLITE_NEW_DBFILE, "IN");
  369. sqlite3_close(db);
  370. // should work now that we closed it
  371. SQLite3Accessor accessor3(SQLITE_NEW_DBFILE, "IN");
  372. }
  373. TEST_F(SQLite3Create, lockedtest) {
  374. ASSERT_FALSE(isReadable(SQLITE_NEW_DBFILE));
  375. // open one manually
  376. sqlite3* db;
  377. ASSERT_EQ(SQLITE_OK, sqlite3_open(SQLITE_NEW_DBFILE, &db));
  378. sqlite3_exec(db, "BEGIN EXCLUSIVE TRANSACTION", NULL, NULL, NULL);
  379. // should not be able to open it
  380. EXPECT_THROW(SQLite3Accessor accessor2(SQLITE_NEW_DBFILE, "IN"),
  381. SQLite3Error);
  382. sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
  383. // should work now that we closed it
  384. SQLite3Accessor accessor3(SQLITE_NEW_DBFILE, "IN");
  385. }
  386. TEST_F(SQLite3AccessorTest, clone) {
  387. shared_ptr<DatabaseAccessor> cloned = accessor->clone();
  388. EXPECT_EQ(accessor->getDBName(), cloned->getDBName());
  389. // The cloned accessor should have a separate connection and search
  390. // context, so it should be able to perform search in concurrent with
  391. // the original accessor.
  392. string columns1[DatabaseAccessor::COLUMN_COUNT];
  393. string columns2[DatabaseAccessor::COLUMN_COUNT];
  394. const std::pair<bool, int> zone_info1(
  395. accessor->getZone("example.com."));
  396. DatabaseAccessor::IteratorContextPtr iterator1 =
  397. accessor->getRecords("foo.example.com.", zone_info1.second);
  398. const std::pair<bool, int> zone_info2(
  399. accessor->getZone("example.com."));
  400. DatabaseAccessor::IteratorContextPtr iterator2 =
  401. cloned->getRecords("foo.example.com.", zone_info2.second);
  402. ASSERT_TRUE(iterator1->getNext(columns1));
  403. checkRecordRow(columns1, "CNAME", "3600", "", "cnametest.example.org.",
  404. "");
  405. ASSERT_TRUE(iterator2->getNext(columns2));
  406. checkRecordRow(columns2, "CNAME", "3600", "", "cnametest.example.org.",
  407. "");
  408. }
  409. //
  410. // Commonly used data for update tests
  411. //
  412. const char* const common_expected_data[] = {
  413. // Test record already stored in the tested sqlite3 DB file.
  414. "foo.bar.example.com.", "com.example.bar.foo.", "3600", "A", "",
  415. "192.0.2.1"
  416. };
  417. const char* const new_data[] = {
  418. // Newly added data commonly used by some of the tests below
  419. "newdata.example.com.", "com.example.newdata.", "3600", "A", "",
  420. "192.0.2.1"
  421. };
  422. const char* const deleted_data[] = {
  423. // Existing data to be removed commonly used by some of the tests below
  424. "foo.bar.example.com.", "A", "192.0.2.1"
  425. };
  426. class SQLite3Update : public SQLite3AccessorTest {
  427. protected:
  428. SQLite3Update() {
  429. // Note: if "installing" the test file fails some of the subsequent
  430. // tests would fail.
  431. const char *install_cmd = INSTALL_PROG " " TEST_DATA_DIR
  432. "/test.sqlite3 " TEST_DATA_BUILDDIR
  433. "/test.sqlite3.copied";
  434. if (system(install_cmd) != 0) {
  435. // any exception will do, this is failure in test setup, but nice
  436. // to show the command that fails, and shouldn't be caught
  437. isc_throw(isc::Exception,
  438. "Error setting up; command failed: " << install_cmd);
  439. };
  440. initAccessor(TEST_DATA_BUILDDIR "/test.sqlite3.copied", "IN");
  441. zone_id = accessor->getZone("example.com.").second;
  442. another_accessor.reset(new SQLite3Accessor(
  443. TEST_DATA_BUILDDIR "/test.sqlite3.copied",
  444. "IN"));
  445. expected_stored.push_back(common_expected_data);
  446. }
  447. int zone_id;
  448. std::string get_columns[DatabaseAccessor::COLUMN_COUNT];
  449. std::string add_columns[DatabaseAccessor::ADD_COLUMN_COUNT];
  450. std::string del_params[DatabaseAccessor::DEL_PARAM_COUNT];
  451. vector<const char* const*> expected_stored; // placeholder for checkRecords
  452. vector<const char* const*> empty_stored; // indicate no corresponding data
  453. // Another accessor, emulating one running on a different process/thread
  454. shared_ptr<SQLite3Accessor> another_accessor;
  455. DatabaseAccessor::IteratorContextPtr iterator;
  456. };
  457. void
  458. checkRecords(SQLite3Accessor& accessor, int zone_id, const std::string& name,
  459. vector<const char* const*> expected_rows)
  460. {
  461. DatabaseAccessor::IteratorContextPtr iterator =
  462. accessor.getRecords(name, zone_id);
  463. std::string columns[DatabaseAccessor::COLUMN_COUNT];
  464. vector<const char* const*>::const_iterator it = expected_rows.begin();
  465. while (iterator->getNext(columns)) {
  466. ASSERT_TRUE(it != expected_rows.end());
  467. checkRecordRow(columns, (*it)[3], (*it)[2], (*it)[4], (*it)[5], "");
  468. ++it;
  469. }
  470. EXPECT_TRUE(it == expected_rows.end());
  471. }
  472. TEST_F(SQLite3Update, emptyUpdate) {
  473. // If we do nothing between start and commit, the zone content
  474. // should be intact.
  475. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  476. zone_id = accessor->startUpdateZone("example.com.", false).second;
  477. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  478. accessor->commitUpdateZone();
  479. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  480. }
  481. TEST_F(SQLite3Update, flushZone) {
  482. // With 'replace' being true startUpdateZone() will flush the existing
  483. // zone content.
  484. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  485. zone_id = accessor->startUpdateZone("example.com.", true).second;
  486. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  487. accessor->commitUpdateZone();
  488. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  489. }
  490. TEST_F(SQLite3Update, readWhileUpdate) {
  491. zone_id = accessor->startUpdateZone("example.com.", true).second;
  492. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  493. // Until commit is done, the other accessor should see the old data
  494. checkRecords(*another_accessor, zone_id, "foo.bar.example.com.",
  495. expected_stored);
  496. // Once the changes are committed, the other accessor will see the new
  497. // data.
  498. accessor->commitUpdateZone();
  499. checkRecords(*another_accessor, zone_id, "foo.bar.example.com.",
  500. empty_stored);
  501. }
  502. TEST_F(SQLite3Update, rollback) {
  503. zone_id = accessor->startUpdateZone("example.com.", true).second;
  504. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  505. // Rollback will revert the change made by startUpdateZone(, true).
  506. accessor->rollbackUpdateZone();
  507. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  508. }
  509. TEST_F(SQLite3Update, rollbackFailure) {
  510. // This test emulates a rare scenario of making rollback attempt fail.
  511. // The iterator is paused in the middle of getting records, which prevents
  512. // the rollback operation at the end of the test.
  513. string columns[DatabaseAccessor::COLUMN_COUNT];
  514. iterator = accessor->getRecords("example.com.", zone_id);
  515. EXPECT_TRUE(iterator->getNext(columns));
  516. accessor->startUpdateZone("example.com.", true);
  517. EXPECT_THROW(accessor->rollbackUpdateZone(), DataSourceError);
  518. }
  519. TEST_F(SQLite3Update, commitConflict) {
  520. // Start reading the DB by another accessor. We should stop at a single
  521. // call to getNextRecord() to keep holding the lock.
  522. iterator = another_accessor->getRecords("foo.example.com.", zone_id);
  523. EXPECT_TRUE(iterator->getNext(get_columns));
  524. // Due to getNextRecord() above, the other accessor holds a DB lock,
  525. // which will prevent commit.
  526. zone_id = accessor->startUpdateZone("example.com.", true).second;
  527. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  528. EXPECT_THROW(accessor->commitUpdateZone(), DataSourceError);
  529. accessor->rollbackUpdateZone(); // rollback should still succeed
  530. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  531. }
  532. TEST_F(SQLite3Update, updateConflict) {
  533. // Similar to the previous case, but this is a conflict with another
  534. // update attempt. Note that these two accessors modify disjoint sets
  535. // of data; sqlite3 only has a coarse-grained lock so we cannot allow
  536. // these updates to run concurrently.
  537. EXPECT_TRUE(another_accessor->startUpdateZone("sql1.example.com.",
  538. true).first);
  539. EXPECT_THROW(accessor->startUpdateZone("example.com.", true),
  540. DataSourceError);
  541. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  542. // Once we rollback the other attempt of change, we should be able to
  543. // start and commit the transaction using the main accessor.
  544. another_accessor->rollbackUpdateZone();
  545. accessor->startUpdateZone("example.com.", true);
  546. accessor->commitUpdateZone();
  547. }
  548. TEST_F(SQLite3Update, duplicateUpdate) {
  549. accessor->startUpdateZone("example.com.", false);
  550. EXPECT_THROW(accessor->startUpdateZone("example.com.", false),
  551. DataSourceError);
  552. }
  553. TEST_F(SQLite3Update, commitWithoutTransaction) {
  554. EXPECT_THROW(accessor->commitUpdateZone(), DataSourceError);
  555. }
  556. TEST_F(SQLite3Update, rollbackWithoutTransaction) {
  557. EXPECT_THROW(accessor->rollbackUpdateZone(), DataSourceError);
  558. }
  559. TEST_F(SQLite3Update, addRecord) {
  560. // Before update, there should be no record for this name
  561. checkRecords(*accessor, zone_id, "newdata.example.com.", empty_stored);
  562. zone_id = accessor->startUpdateZone("example.com.", false).second;
  563. copy(new_data, new_data + DatabaseAccessor::ADD_COLUMN_COUNT,
  564. add_columns);
  565. accessor->addRecordToZone(add_columns);
  566. expected_stored.clear();
  567. expected_stored.push_back(new_data);
  568. checkRecords(*accessor, zone_id, "newdata.example.com.", expected_stored);
  569. // Commit the change, and confirm the new data is still there.
  570. accessor->commitUpdateZone();
  571. checkRecords(*accessor, zone_id, "newdata.example.com.", expected_stored);
  572. }
  573. TEST_F(SQLite3Update, addThenRollback) {
  574. zone_id = accessor->startUpdateZone("example.com.", false).second;
  575. copy(new_data, new_data + DatabaseAccessor::ADD_COLUMN_COUNT,
  576. add_columns);
  577. accessor->addRecordToZone(add_columns);
  578. expected_stored.clear();
  579. expected_stored.push_back(new_data);
  580. checkRecords(*accessor, zone_id, "newdata.example.com.", expected_stored);
  581. accessor->rollbackUpdateZone();
  582. checkRecords(*accessor, zone_id, "newdata.example.com.", empty_stored);
  583. }
  584. TEST_F(SQLite3Update, duplicateAdd) {
  585. const char* const dup_data[] = {
  586. "foo.bar.example.com.", "com.example.bar.foo.", "3600", "A", "",
  587. "192.0.2.1"
  588. };
  589. expected_stored.clear();
  590. expected_stored.push_back(dup_data);
  591. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  592. // Adding exactly the same data. As this backend is "dumb", another
  593. // row of the same content will be inserted.
  594. copy(dup_data, dup_data + DatabaseAccessor::ADD_COLUMN_COUNT,
  595. add_columns);
  596. zone_id = accessor->startUpdateZone("example.com.", false).second;
  597. accessor->addRecordToZone(add_columns);
  598. expected_stored.push_back(dup_data);
  599. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  600. }
  601. TEST_F(SQLite3Update, invalidAdd) {
  602. // An attempt of add before an explicit start of transaction
  603. EXPECT_THROW(accessor->addRecordToZone(add_columns), DataSourceError);
  604. }
  605. TEST_F(SQLite3Update, deleteRecord) {
  606. zone_id = accessor->startUpdateZone("example.com.", false).second;
  607. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  608. copy(deleted_data, deleted_data + DatabaseAccessor::DEL_PARAM_COUNT,
  609. del_params);
  610. accessor->deleteRecordInZone(del_params);
  611. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  612. // Commit the change, and confirm the deleted data still isn't there.
  613. accessor->commitUpdateZone();
  614. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  615. }
  616. TEST_F(SQLite3Update, deleteThenRollback) {
  617. zone_id = accessor->startUpdateZone("example.com.", false).second;
  618. copy(deleted_data, deleted_data + DatabaseAccessor::DEL_PARAM_COUNT,
  619. del_params);
  620. accessor->deleteRecordInZone(del_params);
  621. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  622. // Rollback the change, and confirm the data still exists.
  623. accessor->rollbackUpdateZone();
  624. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  625. }
  626. TEST_F(SQLite3Update, deleteNonexistent) {
  627. zone_id = accessor->startUpdateZone("example.com.", false).second;
  628. copy(deleted_data, deleted_data + DatabaseAccessor::DEL_PARAM_COUNT,
  629. del_params);
  630. // Replace the name with a non existent one, then try to delete it.
  631. // nothing should happen.
  632. del_params[DatabaseAccessor::DEL_NAME] = "no-such-name.example.com.";
  633. checkRecords(*accessor, zone_id, "no-such-name.example.com.",
  634. empty_stored);
  635. accessor->deleteRecordInZone(del_params);
  636. checkRecords(*accessor, zone_id, "no-such-name.example.com.",
  637. empty_stored);
  638. // Name exists but the RR type is different. Delete attempt shouldn't
  639. // delete only by name.
  640. copy(deleted_data, deleted_data + DatabaseAccessor::DEL_PARAM_COUNT,
  641. del_params);
  642. del_params[DatabaseAccessor::DEL_TYPE] = "AAAA";
  643. accessor->deleteRecordInZone(del_params);
  644. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  645. // Similar to the previous case, but RDATA is different.
  646. copy(deleted_data, deleted_data + DatabaseAccessor::DEL_PARAM_COUNT,
  647. del_params);
  648. del_params[DatabaseAccessor::DEL_RDATA] = "192.0.2.2";
  649. accessor->deleteRecordInZone(del_params);
  650. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  651. }
  652. TEST_F(SQLite3Update, invalidDelete) {
  653. // An attempt of delete before an explicit start of transaction
  654. EXPECT_THROW(accessor->deleteRecordInZone(del_params), DataSourceError);
  655. }
  656. } // end anonymous namespace