sqlite3_accessor_unittest.cc 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115
  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/lexical_cast.hpp>
  21. #include <boost/scoped_ptr.hpp>
  22. #include <fstream>
  23. #include <sqlite3.h>
  24. using namespace std;
  25. using namespace isc::datasrc;
  26. using boost::shared_ptr;
  27. using boost::lexical_cast;
  28. using isc::data::ConstElementPtr;
  29. using isc::data::Element;
  30. using isc::dns::RRClass;
  31. using isc::dns::Name;
  32. namespace {
  33. // Some test data
  34. std::string SQLITE_DBFILE_EXAMPLE = TEST_DATA_DIR "/test.sqlite3";
  35. std::string SQLITE_DBFILE_EXAMPLE2 = TEST_DATA_DIR "/example2.com.sqlite3";
  36. std::string SQLITE_DBNAME_EXAMPLE2 = "sqlite3_example2.com.sqlite3";
  37. std::string SQLITE_DBFILE_EXAMPLE_ROOT = TEST_DATA_DIR "/test-root.sqlite3";
  38. std::string SQLITE_DBNAME_EXAMPLE_ROOT = "sqlite3_test-root.sqlite3";
  39. std::string SQLITE_DBFILE_BROKENDB = TEST_DATA_DIR "/brokendb.sqlite3";
  40. std::string SQLITE_DBFILE_MEMORY = ":memory:";
  41. std::string SQLITE_DBFILE_EXAMPLE_ORG = TEST_DATA_DIR "/example.org.sqlite3";
  42. // The following file must be non existent and must be non"creatable";
  43. // the sqlite3 library will try to create a new DB file if it doesn't exist,
  44. // so to test a failure case the create operation should also fail.
  45. // The "nodir", a non existent directory, is inserted for this purpose.
  46. std::string SQLITE_DBFILE_NOTEXIST = TEST_DATA_DIR "/nodir/notexist";
  47. // new db file, we don't need this to be a std::string, and given the
  48. // raw calls we use it in a const char* is more convenient
  49. const char* SQLITE_NEW_DBFILE = TEST_DATA_BUILDDIR "/newdb.sqlite3";
  50. // Opening works (the content is tested in different tests)
  51. TEST(SQLite3Open, common) {
  52. EXPECT_NO_THROW(SQLite3Accessor accessor(SQLITE_DBFILE_EXAMPLE, "IN"));
  53. }
  54. // The file can't be opened
  55. TEST(SQLite3Open, notExist) {
  56. EXPECT_THROW(SQLite3Accessor accessor(SQLITE_DBFILE_NOTEXIST, "IN"),
  57. SQLite3Error);
  58. }
  59. // It rejects broken DB
  60. TEST(SQLite3Open, brokenDB) {
  61. EXPECT_THROW(SQLite3Accessor accessor(SQLITE_DBFILE_BROKENDB, "IN"),
  62. SQLite3Error);
  63. }
  64. // Test we can create the schema on the fly
  65. TEST(SQLite3Open, memoryDB) {
  66. EXPECT_NO_THROW(SQLite3Accessor accessor(SQLITE_DBFILE_MEMORY, "IN"));
  67. }
  68. // Test fixture for querying the db
  69. class SQLite3AccessorTest : public ::testing::Test {
  70. public:
  71. SQLite3AccessorTest() {
  72. initAccessor(SQLITE_DBFILE_EXAMPLE, "IN");
  73. }
  74. // So it can be re-created with different data
  75. void initAccessor(const std::string& filename, const string& rrclass) {
  76. accessor.reset(new SQLite3Accessor(filename, rrclass));
  77. }
  78. // The tested accessor
  79. boost::shared_ptr<SQLite3Accessor> accessor;
  80. };
  81. // This zone exists in the data, so it should be found
  82. TEST_F(SQLite3AccessorTest, getZone) {
  83. std::pair<bool, int> result(accessor->getZone("example.com."));
  84. EXPECT_TRUE(result.first);
  85. EXPECT_EQ(1, result.second);
  86. }
  87. // But it should find only the zone, nothing below it
  88. TEST_F(SQLite3AccessorTest, subZone) {
  89. EXPECT_FALSE(accessor->getZone("sub.example.com.").first);
  90. }
  91. // This zone is not there at all
  92. TEST_F(SQLite3AccessorTest, noZone) {
  93. EXPECT_FALSE(accessor->getZone("example.org.").first);
  94. }
  95. // This zone is there, but in different class
  96. TEST_F(SQLite3AccessorTest, noClass) {
  97. initAccessor(SQLITE_DBFILE_EXAMPLE, "CH");
  98. EXPECT_FALSE(accessor->getZone("example.com.").first);
  99. }
  100. // This tests the iterator context
  101. TEST_F(SQLite3AccessorTest, iterator) {
  102. // Our test zone is conveniently small, but not empty
  103. initAccessor(SQLITE_DBFILE_EXAMPLE_ORG, "IN");
  104. const std::pair<bool, int> zone_info(accessor->getZone("example.org."));
  105. ASSERT_TRUE(zone_info.first);
  106. // Get the iterator context
  107. DatabaseAccessor::IteratorContextPtr
  108. context(accessor->getAllRecords(zone_info.second));
  109. ASSERT_NE(DatabaseAccessor::IteratorContextPtr(), context);
  110. std::string data[DatabaseAccessor::COLUMN_COUNT];
  111. // Get and check the first and only record
  112. EXPECT_TRUE(context->getNext(data));
  113. EXPECT_EQ("MX", data[DatabaseAccessor::TYPE_COLUMN]);
  114. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  115. EXPECT_EQ("10 mail.example.org.", data[DatabaseAccessor::RDATA_COLUMN]);
  116. EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  117. EXPECT_TRUE(context->getNext(data));
  118. EXPECT_EQ("NS", data[DatabaseAccessor::TYPE_COLUMN]);
  119. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  120. EXPECT_EQ("ns1.example.org.", data[DatabaseAccessor::RDATA_COLUMN]);
  121. EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  122. EXPECT_TRUE(context->getNext(data));
  123. EXPECT_EQ("NS", data[DatabaseAccessor::TYPE_COLUMN]);
  124. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  125. EXPECT_EQ("ns2.example.org.", data[DatabaseAccessor::RDATA_COLUMN]);
  126. EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  127. EXPECT_TRUE(context->getNext(data));
  128. EXPECT_EQ("NS", data[DatabaseAccessor::TYPE_COLUMN]);
  129. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  130. EXPECT_EQ("ns3.example.org.", data[DatabaseAccessor::RDATA_COLUMN]);
  131. EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  132. EXPECT_TRUE(context->getNext(data));
  133. EXPECT_EQ("SOA", data[DatabaseAccessor::TYPE_COLUMN]);
  134. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  135. EXPECT_EQ("ns1.example.org. admin.example.org. "
  136. "1234 3600 1800 2419200 7200",
  137. data[DatabaseAccessor::RDATA_COLUMN]);
  138. EXPECT_EQ("example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  139. EXPECT_TRUE(context->getNext(data));
  140. EXPECT_EQ("DNAME", data[DatabaseAccessor::TYPE_COLUMN]);
  141. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  142. EXPECT_EQ("dname.example.info.", data[DatabaseAccessor::RDATA_COLUMN]);
  143. EXPECT_EQ("dname.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  144. EXPECT_TRUE(context->getNext(data));
  145. EXPECT_EQ("DNAME", data[DatabaseAccessor::TYPE_COLUMN]);
  146. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  147. EXPECT_EQ("dname2.example.info.", data[DatabaseAccessor::RDATA_COLUMN]);
  148. EXPECT_EQ("dname2.foo.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  149. EXPECT_TRUE(context->getNext(data));
  150. EXPECT_EQ("A", data[DatabaseAccessor::TYPE_COLUMN]);
  151. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  152. EXPECT_EQ("192.0.2.10", data[DatabaseAccessor::RDATA_COLUMN]);
  153. EXPECT_EQ("mail.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  154. EXPECT_TRUE(context->getNext(data));
  155. EXPECT_EQ("NS", data[DatabaseAccessor::TYPE_COLUMN]);
  156. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  157. EXPECT_EQ("ns.sub.example.org.", data[DatabaseAccessor::RDATA_COLUMN]);
  158. EXPECT_EQ("sub.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  159. EXPECT_TRUE(context->getNext(data));
  160. EXPECT_EQ("A", data[DatabaseAccessor::TYPE_COLUMN]);
  161. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  162. EXPECT_EQ("192.0.2.101", data[DatabaseAccessor::RDATA_COLUMN]);
  163. EXPECT_EQ("ns.sub.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  164. EXPECT_TRUE(context->getNext(data));
  165. EXPECT_EQ("A", data[DatabaseAccessor::TYPE_COLUMN]);
  166. EXPECT_EQ("3600", data[DatabaseAccessor::TTL_COLUMN]);
  167. EXPECT_EQ("192.0.2.1", data[DatabaseAccessor::RDATA_COLUMN]);
  168. EXPECT_EQ("www.example.org.", data[DatabaseAccessor::NAME_COLUMN]);
  169. // Check there's no other
  170. EXPECT_FALSE(context->getNext(data));
  171. // And make sure calling it again won't cause problems.
  172. EXPECT_FALSE(context->getNext(data));
  173. }
  174. TEST(SQLite3Open, getDBNameExample2) {
  175. SQLite3Accessor accessor(SQLITE_DBFILE_EXAMPLE2, "IN");
  176. EXPECT_EQ(SQLITE_DBNAME_EXAMPLE2, accessor.getDBName());
  177. }
  178. TEST(SQLite3Open, getDBNameExampleROOT) {
  179. SQLite3Accessor accessor(SQLITE_DBFILE_EXAMPLE_ROOT, "IN");
  180. EXPECT_EQ(SQLITE_DBNAME_EXAMPLE_ROOT, accessor.getDBName());
  181. }
  182. // Simple function to match records
  183. void
  184. checkRecordRow(const std::string columns[],
  185. const std::string& field0,
  186. const std::string& field1,
  187. const std::string& field2,
  188. const std::string& field3,
  189. const std::string& field4)
  190. {
  191. EXPECT_EQ(field0, columns[DatabaseAccessor::TYPE_COLUMN]);
  192. EXPECT_EQ(field1, columns[DatabaseAccessor::TTL_COLUMN]);
  193. EXPECT_EQ(field2, columns[DatabaseAccessor::SIGTYPE_COLUMN]);
  194. EXPECT_EQ(field3, columns[DatabaseAccessor::RDATA_COLUMN]);
  195. EXPECT_EQ(field4, columns[DatabaseAccessor::NAME_COLUMN]);
  196. }
  197. TEST_F(SQLite3AccessorTest, getRecords) {
  198. const std::pair<bool, int> zone_info(accessor->getZone("example.com."));
  199. ASSERT_TRUE(zone_info.first);
  200. const int zone_id = zone_info.second;
  201. ASSERT_EQ(1, zone_id);
  202. std::string columns[DatabaseAccessor::COLUMN_COUNT];
  203. DatabaseAccessor::IteratorContextPtr
  204. context(accessor->getRecords("foo.bar", 1));
  205. ASSERT_NE(DatabaseAccessor::IteratorContextPtr(),
  206. context);
  207. EXPECT_FALSE(context->getNext(columns));
  208. checkRecordRow(columns, "", "", "", "", "");
  209. // now try some real searches
  210. context = accessor->getRecords("foo.example.com.", zone_id);
  211. ASSERT_TRUE(context->getNext(columns));
  212. checkRecordRow(columns, "CNAME", "3600", "",
  213. "cnametest.example.org.", "");
  214. ASSERT_TRUE(context->getNext(columns));
  215. checkRecordRow(columns, "RRSIG", "3600", "CNAME",
  216. "CNAME 5 3 3600 20100322084538 20100220084538 33495 "
  217. "example.com. FAKEFAKEFAKEFAKE", "");
  218. ASSERT_TRUE(context->getNext(columns));
  219. checkRecordRow(columns, "NSEC", "7200", "",
  220. "mail.example.com. CNAME RRSIG NSEC", "");
  221. ASSERT_TRUE(context->getNext(columns));
  222. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  223. "NSEC 5 3 7200 20100322084538 20100220084538 33495 "
  224. "example.com. FAKEFAKEFAKEFAKE", "");
  225. EXPECT_FALSE(context->getNext(columns));
  226. // with no more records, the array should not have been modified
  227. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  228. "NSEC 5 3 7200 20100322084538 20100220084538 33495 "
  229. "example.com. FAKEFAKEFAKEFAKE", "");
  230. context = accessor->getRecords("example.com.", zone_id);
  231. ASSERT_TRUE(context->getNext(columns));
  232. checkRecordRow(columns, "SOA", "3600", "",
  233. "master.example.com. admin.example.com. "
  234. "1234 3600 1800 2419200 7200", "");
  235. ASSERT_TRUE(context->getNext(columns));
  236. checkRecordRow(columns, "RRSIG", "3600", "SOA",
  237. "SOA 5 2 3600 20100322084538 20100220084538 "
  238. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  239. ASSERT_TRUE(context->getNext(columns));
  240. checkRecordRow(columns, "NS", "1200", "", "dns01.example.com.", "");
  241. ASSERT_TRUE(context->getNext(columns));
  242. checkRecordRow(columns, "NS", "3600", "", "dns02.example.com.", "");
  243. ASSERT_TRUE(context->getNext(columns));
  244. checkRecordRow(columns, "NS", "1800", "", "dns03.example.com.", "");
  245. ASSERT_TRUE(context->getNext(columns));
  246. checkRecordRow(columns, "RRSIG", "3600", "NS",
  247. "NS 5 2 3600 20100322084538 20100220084538 "
  248. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  249. ASSERT_TRUE(context->getNext(columns));
  250. checkRecordRow(columns, "MX", "3600", "", "10 mail.example.com.", "");
  251. ASSERT_TRUE(context->getNext(columns));
  252. checkRecordRow(columns, "MX", "3600", "",
  253. "20 mail.subzone.example.com.", "");
  254. ASSERT_TRUE(context->getNext(columns));
  255. checkRecordRow(columns, "RRSIG", "3600", "MX",
  256. "MX 5 2 3600 20100322084538 20100220084538 "
  257. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  258. ASSERT_TRUE(context->getNext(columns));
  259. checkRecordRow(columns, "NSEC", "7200", "",
  260. "cname-ext.example.com. NS SOA MX RRSIG NSEC DNSKEY", "");
  261. ASSERT_TRUE(context->getNext(columns));
  262. checkRecordRow(columns, "RRSIG", "7200", "NSEC",
  263. "NSEC 5 2 7200 20100322084538 20100220084538 "
  264. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  265. ASSERT_TRUE(context->getNext(columns));
  266. checkRecordRow(columns, "DNSKEY", "3600", "",
  267. "256 3 5 AwEAAcOUBllYc1hf7ND9uDy+Yz1BF3sI0m4q NGV7W"
  268. "cTD0WEiuV7IjXgHE36fCmS9QsUxSSOV o1I/FMxI2PJVqTYHkX"
  269. "FBS7AzLGsQYMU7UjBZ SotBJ6Imt5pXMu+lEDNy8TOUzG3xm7g"
  270. "0qcbW YF6qCEfvZoBtAqi5Rk7Mlrqs8agxYyMx", "");
  271. ASSERT_TRUE(context->getNext(columns));
  272. checkRecordRow(columns, "DNSKEY", "3600", "",
  273. "257 3 5 AwEAAe5WFbxdCPq2jZrZhlMj7oJdff3W7syJ tbvzg"
  274. "62tRx0gkoCDoBI9DPjlOQG0UAbj+xUV 4HQZJStJaZ+fHU5AwV"
  275. "NT+bBZdtV+NujSikhd THb4FYLg2b3Cx9NyJvAVukHp/91HnWu"
  276. "G4T36 CzAFrfPwsHIrBz9BsaIQ21VRkcmj7DswfI/i DGd8j6b"
  277. "qiODyNZYQ+ZrLmF0KIJ2yPN3iO6Zq 23TaOrVTjB7d1a/h31OD"
  278. "fiHAxFHrkY3t3D5J R9Nsl/7fdRmSznwtcSDgLXBoFEYmw6p86"
  279. "Acv RyoYNcL1SXjaKVLG5jyU3UR+LcGZT5t/0xGf oIK/aKwEN"
  280. "rsjcKZZj660b1M=", "");
  281. ASSERT_TRUE(context->getNext(columns));
  282. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  283. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  284. "4456 example.com. FAKEFAKEFAKEFAKE", "");
  285. ASSERT_TRUE(context->getNext(columns));
  286. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  287. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  288. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  289. EXPECT_FALSE(context->getNext(columns));
  290. // getnextrecord returning false should mean array is not altered
  291. checkRecordRow(columns, "RRSIG", "3600", "DNSKEY",
  292. "DNSKEY 5 2 3600 20100322084538 20100220084538 "
  293. "33495 example.com. FAKEFAKEFAKEFAKE", "");
  294. // check that another getNext does not cause problems
  295. EXPECT_FALSE(context->getNext(columns));
  296. // Try searching for subdomain
  297. // There's foo.bar.example.com in the data
  298. context = accessor->getRecords("bar.example.com.", zone_id, true);
  299. ASSERT_TRUE(context->getNext(columns));
  300. checkRecordRow(columns, "A", "3600", "", "192.0.2.1", "");
  301. EXPECT_FALSE(context->getNext(columns));
  302. // But we shouldn't match mix.example.com here
  303. context = accessor->getRecords("ix.example.com.", zone_id, true);
  304. EXPECT_FALSE(context->getNext(columns));
  305. }
  306. TEST_F(SQLite3AccessorTest, findPrevious) {
  307. EXPECT_EQ("dns01.example.com.",
  308. accessor->findPreviousName(1, "com.example.dns02."));
  309. // A name that doesn't exist
  310. EXPECT_EQ("dns01.example.com.",
  311. accessor->findPreviousName(1, "com.example.dns01x."));
  312. // Largest name
  313. EXPECT_EQ("www.example.com.",
  314. accessor->findPreviousName(1, "com.example.wwww"));
  315. // Out of zone after the last name
  316. EXPECT_EQ("www.example.com.",
  317. accessor->findPreviousName(1, "org.example."));
  318. // Case insensitive?
  319. EXPECT_EQ("dns01.example.com.",
  320. accessor->findPreviousName(1, "com.exaMple.DNS02."));
  321. // A name that doesn't exist
  322. EXPECT_EQ("dns01.example.com.",
  323. accessor->findPreviousName(1, "com.exaMple.DNS01X."));
  324. // The DB contains foo.bar.example.com., which would be in between
  325. // these two names. However, that one does not have an NSEC record,
  326. // which is how this database recognizes glue data, so it should
  327. // be skipped.
  328. EXPECT_EQ("example.com.",
  329. accessor->findPreviousName(1, "com.example.cname-ext."));
  330. // Throw when we are before the origin
  331. EXPECT_THROW(accessor->findPreviousName(1, "com.example."),
  332. isc::NotImplemented);
  333. EXPECT_THROW(accessor->findPreviousName(1, "a.example."),
  334. isc::NotImplemented);
  335. }
  336. TEST_F(SQLite3AccessorTest, findPreviousNoData) {
  337. // This one doesn't hold any NSEC records, so it shouldn't work
  338. // The underlying DB/data don't support DNSSEC, so it's not implemented
  339. // (does it make sense? Or different exception here?)
  340. EXPECT_THROW(accessor->findPreviousName(3, "com.example.sql2.www."),
  341. isc::NotImplemented);
  342. }
  343. // Test fixture for creating a db that automatically deletes it before start,
  344. // and when done
  345. class SQLite3Create : public ::testing::Test {
  346. public:
  347. SQLite3Create() {
  348. remove(SQLITE_NEW_DBFILE);
  349. }
  350. ~SQLite3Create() {
  351. remove(SQLITE_NEW_DBFILE);
  352. }
  353. };
  354. bool isReadable(const char* filename) {
  355. return (std::ifstream(filename).is_open());
  356. }
  357. TEST_F(SQLite3Create, creationtest) {
  358. ASSERT_FALSE(isReadable(SQLITE_NEW_DBFILE));
  359. // Should simply be created
  360. SQLite3Accessor accessor(SQLITE_NEW_DBFILE, "IN");
  361. ASSERT_TRUE(isReadable(SQLITE_NEW_DBFILE));
  362. }
  363. TEST_F(SQLite3Create, emptytest) {
  364. ASSERT_FALSE(isReadable(SQLITE_NEW_DBFILE));
  365. // open one manualle
  366. sqlite3* db;
  367. ASSERT_EQ(SQLITE_OK, sqlite3_open(SQLITE_NEW_DBFILE, &db));
  368. // empty, but not locked, so creating it now should work
  369. SQLite3Accessor accessor2(SQLITE_NEW_DBFILE, "IN");
  370. sqlite3_close(db);
  371. // should work now that we closed it
  372. SQLite3Accessor accessor3(SQLITE_NEW_DBFILE, "IN");
  373. }
  374. TEST_F(SQLite3Create, lockedtest) {
  375. ASSERT_FALSE(isReadable(SQLITE_NEW_DBFILE));
  376. // open one manually
  377. sqlite3* db;
  378. ASSERT_EQ(SQLITE_OK, sqlite3_open(SQLITE_NEW_DBFILE, &db));
  379. sqlite3_exec(db, "BEGIN EXCLUSIVE TRANSACTION", NULL, NULL, NULL);
  380. // should not be able to open it
  381. EXPECT_THROW(SQLite3Accessor accessor2(SQLITE_NEW_DBFILE, "IN"),
  382. SQLite3Error);
  383. sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
  384. // should work now that we closed it
  385. SQLite3Accessor accessor3(SQLITE_NEW_DBFILE, "IN");
  386. }
  387. TEST_F(SQLite3AccessorTest, clone) {
  388. shared_ptr<DatabaseAccessor> cloned = accessor->clone();
  389. EXPECT_EQ(accessor->getDBName(), cloned->getDBName());
  390. // The cloned accessor should have a separate connection and search
  391. // context, so it should be able to perform search in concurrent with
  392. // the original accessor.
  393. string columns1[DatabaseAccessor::COLUMN_COUNT];
  394. string columns2[DatabaseAccessor::COLUMN_COUNT];
  395. const std::pair<bool, int> zone_info1(
  396. accessor->getZone("example.com."));
  397. DatabaseAccessor::IteratorContextPtr iterator1 =
  398. accessor->getRecords("foo.example.com.", zone_info1.second);
  399. const std::pair<bool, int> zone_info2(
  400. accessor->getZone("example.com."));
  401. DatabaseAccessor::IteratorContextPtr iterator2 =
  402. cloned->getRecords("foo.example.com.", zone_info2.second);
  403. ASSERT_TRUE(iterator1->getNext(columns1));
  404. checkRecordRow(columns1, "CNAME", "3600", "", "cnametest.example.org.",
  405. "");
  406. ASSERT_TRUE(iterator2->getNext(columns2));
  407. checkRecordRow(columns2, "CNAME", "3600", "", "cnametest.example.org.",
  408. "");
  409. }
  410. //
  411. // Commonly used data for update tests
  412. //
  413. const char* const common_expected_data[] = {
  414. // Test record already stored in the tested sqlite3 DB file.
  415. "foo.bar.example.com.", "com.example.bar.foo.", "3600", "A", "",
  416. "192.0.2.1"
  417. };
  418. const char* const new_data[] = {
  419. // Newly added data commonly used by some of the tests below
  420. "newdata.example.com.", "com.example.newdata.", "3600", "A", "",
  421. "192.0.2.1"
  422. };
  423. const char* const deleted_data[] = {
  424. // Existing data to be removed commonly used by some of the tests below
  425. "foo.bar.example.com.", "A", "192.0.2.1"
  426. };
  427. class SQLite3Update : public SQLite3AccessorTest {
  428. protected:
  429. SQLite3Update() {
  430. // Note: if "installing" the test file fails some of the subsequent
  431. // tests would fail.
  432. const char *install_cmd = INSTALL_PROG " " TEST_DATA_DIR
  433. "/test.sqlite3 " TEST_DATA_BUILDDIR
  434. "/test.sqlite3.copied";
  435. if (system(install_cmd) != 0) {
  436. // any exception will do, this is failure in test setup, but nice
  437. // to show the command that fails, and shouldn't be caught
  438. isc_throw(isc::Exception,
  439. "Error setting up; command failed: " << install_cmd);
  440. };
  441. initAccessor(TEST_DATA_BUILDDIR "/test.sqlite3.copied", "IN");
  442. zone_id = accessor->getZone("example.com.").second;
  443. another_accessor.reset(new SQLite3Accessor(
  444. TEST_DATA_BUILDDIR "/test.sqlite3.copied",
  445. "IN"));
  446. expected_stored.push_back(common_expected_data);
  447. }
  448. int zone_id;
  449. std::string get_columns[DatabaseAccessor::COLUMN_COUNT];
  450. std::string add_columns[DatabaseAccessor::ADD_COLUMN_COUNT];
  451. std::string del_params[DatabaseAccessor::DEL_PARAM_COUNT];
  452. std::string diff_params[DatabaseAccessor::DIFF_PARAM_COUNT];
  453. vector<const char* const*> expected_stored; // placeholder for checkRecords
  454. vector<const char* const*> empty_stored; // indicate no corresponding data
  455. // Another accessor, emulating one running on a different process/thread
  456. shared_ptr<SQLite3Accessor> another_accessor;
  457. DatabaseAccessor::IteratorContextPtr iterator;
  458. };
  459. void
  460. checkRecords(SQLite3Accessor& accessor, int zone_id, const std::string& name,
  461. vector<const char* const*> expected_rows)
  462. {
  463. DatabaseAccessor::IteratorContextPtr iterator =
  464. accessor.getRecords(name, zone_id);
  465. std::string columns[DatabaseAccessor::COLUMN_COUNT];
  466. vector<const char* const*>::const_iterator it = expected_rows.begin();
  467. while (iterator->getNext(columns)) {
  468. ASSERT_TRUE(it != expected_rows.end());
  469. checkRecordRow(columns, (*it)[3], (*it)[2], (*it)[4], (*it)[5], "");
  470. ++it;
  471. }
  472. EXPECT_TRUE(it == expected_rows.end());
  473. }
  474. TEST_F(SQLite3Update, emptyUpdate) {
  475. // If we do nothing between start and commit, the zone content
  476. // should be intact.
  477. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  478. zone_id = accessor->startUpdateZone("example.com.", false).second;
  479. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  480. accessor->commit();
  481. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  482. }
  483. TEST_F(SQLite3Update, flushZone) {
  484. // With 'replace' being true startUpdateZone() will flush the existing
  485. // zone content.
  486. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  487. zone_id = accessor->startUpdateZone("example.com.", true).second;
  488. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  489. accessor->commit();
  490. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  491. }
  492. TEST_F(SQLite3Update, readWhileUpdate) {
  493. zone_id = accessor->startUpdateZone("example.com.", true).second;
  494. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  495. // Until commit is done, the other accessor should see the old data
  496. checkRecords(*another_accessor, zone_id, "foo.bar.example.com.",
  497. expected_stored);
  498. // Once the changes are committed, the other accessor will see the new
  499. // data.
  500. accessor->commit();
  501. checkRecords(*another_accessor, zone_id, "foo.bar.example.com.",
  502. empty_stored);
  503. }
  504. TEST_F(SQLite3Update, rollback) {
  505. zone_id = accessor->startUpdateZone("example.com.", true).second;
  506. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  507. // Rollback will revert the change made by startUpdateZone(, true).
  508. accessor->rollback();
  509. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  510. }
  511. TEST_F(SQLite3Update, rollbackFailure) {
  512. // This test emulates a rare scenario of making rollback attempt fail.
  513. // The iterator is paused in the middle of getting records, which prevents
  514. // the rollback operation at the end of the test.
  515. string columns[DatabaseAccessor::COLUMN_COUNT];
  516. iterator = accessor->getRecords("example.com.", zone_id);
  517. EXPECT_TRUE(iterator->getNext(columns));
  518. accessor->startUpdateZone("example.com.", true);
  519. EXPECT_THROW(accessor->rollback(), DataSourceError);
  520. }
  521. TEST_F(SQLite3Update, commitConflict) {
  522. // Start reading the DB by another accessor. We should stop at a single
  523. // call to getNextRecord() to keep holding the lock.
  524. iterator = another_accessor->getRecords("foo.example.com.", zone_id);
  525. EXPECT_TRUE(iterator->getNext(get_columns));
  526. // Due to getNextRecord() above, the other accessor holds a DB lock,
  527. // which will prevent commit.
  528. zone_id = accessor->startUpdateZone("example.com.", true).second;
  529. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  530. EXPECT_THROW(accessor->commit(), DataSourceError);
  531. accessor->rollback(); // rollback should still succeed
  532. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  533. }
  534. TEST_F(SQLite3Update, updateConflict) {
  535. // Similar to the previous case, but this is a conflict with another
  536. // update attempt. Note that these two accessors modify disjoint sets
  537. // of data; sqlite3 only has a coarse-grained lock so we cannot allow
  538. // these updates to run concurrently.
  539. EXPECT_TRUE(another_accessor->startUpdateZone("sql1.example.com.",
  540. true).first);
  541. EXPECT_THROW(accessor->startUpdateZone("example.com.", true),
  542. DataSourceError);
  543. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  544. // Once we rollback the other attempt of change, we should be able to
  545. // start and commit the transaction using the main accessor.
  546. another_accessor->rollback();
  547. accessor->startUpdateZone("example.com.", true);
  548. accessor->commit();
  549. }
  550. TEST_F(SQLite3Update, duplicateUpdate) {
  551. accessor->startUpdateZone("example.com.", false);
  552. EXPECT_THROW(accessor->startUpdateZone("example.com.", false),
  553. DataSourceError);
  554. }
  555. TEST_F(SQLite3Update, commitWithoutTransaction) {
  556. EXPECT_THROW(accessor->commit(), DataSourceError);
  557. }
  558. TEST_F(SQLite3Update, rollbackWithoutTransaction) {
  559. EXPECT_THROW(accessor->rollback(), DataSourceError);
  560. }
  561. TEST_F(SQLite3Update, addRecord) {
  562. // Before update, there should be no record for this name
  563. checkRecords(*accessor, zone_id, "newdata.example.com.", empty_stored);
  564. zone_id = accessor->startUpdateZone("example.com.", false).second;
  565. copy(new_data, new_data + DatabaseAccessor::ADD_COLUMN_COUNT,
  566. add_columns);
  567. accessor->addRecordToZone(add_columns);
  568. expected_stored.clear();
  569. expected_stored.push_back(new_data);
  570. checkRecords(*accessor, zone_id, "newdata.example.com.", expected_stored);
  571. // Commit the change, and confirm the new data is still there.
  572. accessor->commit();
  573. checkRecords(*accessor, zone_id, "newdata.example.com.", expected_stored);
  574. }
  575. TEST_F(SQLite3Update, addThenRollback) {
  576. zone_id = accessor->startUpdateZone("example.com.", false).second;
  577. copy(new_data, new_data + DatabaseAccessor::ADD_COLUMN_COUNT,
  578. add_columns);
  579. accessor->addRecordToZone(add_columns);
  580. expected_stored.clear();
  581. expected_stored.push_back(new_data);
  582. checkRecords(*accessor, zone_id, "newdata.example.com.", expected_stored);
  583. accessor->rollback();
  584. checkRecords(*accessor, zone_id, "newdata.example.com.", empty_stored);
  585. }
  586. TEST_F(SQLite3Update, duplicateAdd) {
  587. const char* const dup_data[] = {
  588. "foo.bar.example.com.", "com.example.bar.foo.", "3600", "A", "",
  589. "192.0.2.1"
  590. };
  591. expected_stored.clear();
  592. expected_stored.push_back(dup_data);
  593. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  594. // Adding exactly the same data. As this backend is "dumb", another
  595. // row of the same content will be inserted.
  596. copy(dup_data, dup_data + DatabaseAccessor::ADD_COLUMN_COUNT,
  597. add_columns);
  598. zone_id = accessor->startUpdateZone("example.com.", false).second;
  599. accessor->addRecordToZone(add_columns);
  600. expected_stored.push_back(dup_data);
  601. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  602. }
  603. TEST_F(SQLite3Update, invalidAdd) {
  604. // An attempt of add before an explicit start of transaction
  605. EXPECT_THROW(accessor->addRecordToZone(add_columns), DataSourceError);
  606. }
  607. TEST_F(SQLite3Update, deleteRecord) {
  608. zone_id = accessor->startUpdateZone("example.com.", false).second;
  609. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  610. copy(deleted_data, deleted_data + DatabaseAccessor::DEL_PARAM_COUNT,
  611. del_params);
  612. accessor->deleteRecordInZone(del_params);
  613. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  614. // Commit the change, and confirm the deleted data still isn't there.
  615. accessor->commit();
  616. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  617. }
  618. TEST_F(SQLite3Update, deleteThenRollback) {
  619. zone_id = accessor->startUpdateZone("example.com.", false).second;
  620. copy(deleted_data, deleted_data + DatabaseAccessor::DEL_PARAM_COUNT,
  621. del_params);
  622. accessor->deleteRecordInZone(del_params);
  623. checkRecords(*accessor, zone_id, "foo.bar.example.com.", empty_stored);
  624. // Rollback the change, and confirm the data still exists.
  625. accessor->rollback();
  626. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  627. }
  628. TEST_F(SQLite3Update, deleteNonexistent) {
  629. zone_id = accessor->startUpdateZone("example.com.", false).second;
  630. copy(deleted_data, deleted_data + DatabaseAccessor::DEL_PARAM_COUNT,
  631. del_params);
  632. // Replace the name with a non existent one, then try to delete it.
  633. // nothing should happen.
  634. del_params[DatabaseAccessor::DEL_NAME] = "no-such-name.example.com.";
  635. checkRecords(*accessor, zone_id, "no-such-name.example.com.",
  636. empty_stored);
  637. accessor->deleteRecordInZone(del_params);
  638. checkRecords(*accessor, zone_id, "no-such-name.example.com.",
  639. empty_stored);
  640. // Name exists but the RR type is different. Delete attempt shouldn't
  641. // delete only by name.
  642. copy(deleted_data, deleted_data + DatabaseAccessor::DEL_PARAM_COUNT,
  643. del_params);
  644. del_params[DatabaseAccessor::DEL_TYPE] = "AAAA";
  645. accessor->deleteRecordInZone(del_params);
  646. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  647. // Similar to the previous case, but RDATA is different.
  648. copy(deleted_data, deleted_data + DatabaseAccessor::DEL_PARAM_COUNT,
  649. del_params);
  650. del_params[DatabaseAccessor::DEL_RDATA] = "192.0.2.2";
  651. accessor->deleteRecordInZone(del_params);
  652. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  653. }
  654. TEST_F(SQLite3Update, invalidDelete) {
  655. // An attempt of delete before an explicit start of transaction
  656. EXPECT_THROW(accessor->deleteRecordInZone(del_params), DataSourceError);
  657. }
  658. TEST_F(SQLite3Update, emptyTransaction) {
  659. // A generic transaction without doing anything inside it. Just check
  660. // it doesn't throw or break the database.
  661. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  662. accessor->startTransaction();
  663. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  664. accessor->commit();
  665. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  666. }
  667. TEST_F(SQLite3Update, duplicateTransaction) {
  668. accessor->startTransaction();
  669. EXPECT_THROW(accessor->startTransaction(), DataSourceError);
  670. }
  671. TEST_F(SQLite3Update, transactionInUpdate) {
  672. accessor->startUpdateZone("example.com.", true);
  673. EXPECT_THROW(accessor->startTransaction(), DataSourceError);
  674. }
  675. TEST_F(SQLite3Update, updateInTransaction) {
  676. accessor->startTransaction();
  677. EXPECT_THROW(accessor->startUpdateZone("example.com.", true),
  678. DataSourceError);
  679. }
  680. TEST_F(SQLite3Update, updateWithTransaction) {
  681. // Start a read-only transaction, wherein we execute two reads.
  682. // Meanwhile we start a write (update) transaction. The commit attempt
  683. // for the write transaction will due to the lock held by the read
  684. // transaction. The database should be intact.
  685. another_accessor->startTransaction();
  686. checkRecords(*another_accessor, zone_id, "foo.bar.example.com.",
  687. expected_stored);
  688. ASSERT_TRUE(accessor->startUpdateZone("example.com.", true).first);
  689. EXPECT_THROW(accessor->commit(), DataSourceError);
  690. checkRecords(*another_accessor, zone_id, "foo.bar.example.com.",
  691. expected_stored);
  692. another_accessor->commit(); // this shouldn't throw
  693. }
  694. TEST_F(SQLite3Update, updateWithoutTransaction) {
  695. // Similar to the previous test, but reads are not protected in a
  696. // transaction. So the write transaction will succeed and flush the DB,
  697. // and the result of the second read is different from the first.
  698. checkRecords(*another_accessor, zone_id, "foo.bar.example.com.",
  699. expected_stored);
  700. ASSERT_TRUE(accessor->startUpdateZone("example.com.", true).first);
  701. accessor->commit();
  702. checkRecords(*another_accessor, zone_id, "foo.bar.example.com.",
  703. empty_stored);
  704. }
  705. TEST_F(SQLite3Update, concurrentTransactions) {
  706. // Two read-only transactions coexist (unlike the read vs write)
  707. // Start one transaction.
  708. accessor->startTransaction();
  709. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  710. // Start a new one.
  711. another_accessor->startTransaction();
  712. // The second transaction doesn't affect the first or vice versa.
  713. checkRecords(*accessor, zone_id, "foo.bar.example.com.", expected_stored);
  714. checkRecords(*another_accessor, zone_id, "foo.bar.example.com.",
  715. expected_stored);
  716. // Commit should be successful for both transactions.
  717. accessor->commit();
  718. another_accessor->commit();
  719. }
  720. //
  721. // Commonly used data for diff related tests. The last two entries are
  722. // a textual representation of "version" and a textual representation of
  723. // diff operation (either DIFF_ADD_TEXT or DIFF_DELETE_TEXT). We use this
  724. // format for the convenience of generating test data and checking the results.
  725. //
  726. const char* const DIFF_ADD_TEXT = "0";
  727. const char* const DIFF_DELETE_TEXT = "1";
  728. const char* const diff_begin_data[] = {
  729. "example.com.", "SOA", "3600",
  730. "ns.example.com. admin.example.com. 1234 3600 1800 2419200 7200",
  731. "1234", DIFF_DELETE_TEXT
  732. };
  733. const char* const diff_del_a_data[] = {
  734. "dns01.example.com.", "A", "3600", "192.0.2.1", "1234", DIFF_DELETE_TEXT
  735. };
  736. const char* const diff_end_data[] = {
  737. "example.com.", "SOA", "3600",
  738. "ns.example.com. admin.example.com. 1300 3600 1800 2419200 7200",
  739. "1300", DIFF_ADD_TEXT
  740. };
  741. const char* const diff_add_a_data[] = {
  742. "dns01.example.com.", "A", "3600", "192.0.2.10", "1234", DIFF_ADD_TEXT
  743. };
  744. // The following two are helper functions to convert textual test data
  745. // to integral zone ID and diff operation.
  746. int
  747. getVersion(const char* const diff_data[]) {
  748. return (lexical_cast<int>(diff_data[DatabaseAccessor::DIFF_PARAM_COUNT]));
  749. }
  750. DatabaseAccessor::DiffOperation
  751. getOperation(const char* const diff_data[]) {
  752. return (static_cast<DatabaseAccessor::DiffOperation>(
  753. lexical_cast<int>(
  754. diff_data[DatabaseAccessor::DIFF_PARAM_COUNT + 1])));
  755. }
  756. // Common checker function that compares expected and actual sequence of
  757. // diffs.
  758. void
  759. checkDiffs(const vector<const char* const*>& expected,
  760. const vector<vector<string> >& actual)
  761. {
  762. EXPECT_EQ(expected.size(), actual.size());
  763. const size_t n_diffs = std::min(expected.size(), actual.size());
  764. for (size_t i = 0; i < n_diffs; ++i) {
  765. for (int j = 0; j < actual[i].size(); ++j) {
  766. EXPECT_EQ(expected[i][j], actual[i][j]);
  767. }
  768. }
  769. }
  770. TEST_F(SQLite3Update, addRecordDiff) {
  771. // A simple case of adding diffs: just changing the SOA, and confirm
  772. // the diffs are stored as expected.
  773. zone_id = accessor->startUpdateZone("example.com.", false).second;
  774. copy(diff_begin_data, diff_begin_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  775. diff_params);
  776. accessor->addRecordDiff(zone_id, getVersion(diff_begin_data),
  777. getOperation(diff_begin_data), diff_params);
  778. copy(diff_end_data, diff_end_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  779. diff_params);
  780. accessor->addRecordDiff(zone_id, getVersion(diff_end_data),
  781. getOperation(diff_end_data), diff_params);
  782. // Until the diffs are committed, they are not visible to other accessors.
  783. EXPECT_TRUE(another_accessor->getRecordDiff(zone_id).empty());
  784. accessor->commit();
  785. expected_stored.clear();
  786. expected_stored.push_back(diff_begin_data);
  787. expected_stored.push_back(diff_end_data);
  788. checkDiffs(expected_stored, accessor->getRecordDiff(zone_id));
  789. // Now it should be visible to others, too.
  790. checkDiffs(expected_stored, another_accessor->getRecordDiff(zone_id));
  791. }
  792. TEST_F(SQLite3Update, addRecordOfLargeSerial) {
  793. // This is essentially the same as the previous test, but using a
  794. // very large "version" (SOA serial), which is actually the possible
  795. // largest value to confirm the internal code doesn't have an overflow bug
  796. // or other failure due to the larger value.
  797. zone_id = accessor->startUpdateZone("example.com.", false).second;
  798. const char* const begin_data[] = {
  799. "example.com.", "SOA", "3600",
  800. "ns.example.com. admin.example.com. 4294967295 3600 1800 2419200 7200",
  801. "4294967295", DIFF_DELETE_TEXT
  802. };
  803. copy(begin_data, begin_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  804. diff_params);
  805. // For "serial" parameter, we intentionally hardcode the value rather
  806. // than converting it from the data.
  807. accessor->addRecordDiff(zone_id, 0xffffffff, getOperation(diff_begin_data),
  808. diff_params);
  809. copy(diff_end_data, diff_end_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  810. diff_params);
  811. accessor->addRecordDiff(zone_id, getVersion(diff_end_data),
  812. getOperation(diff_end_data), diff_params);
  813. accessor->commit();
  814. expected_stored.clear();
  815. expected_stored.push_back(begin_data);
  816. expected_stored.push_back(diff_end_data);
  817. checkDiffs(expected_stored, accessor->getRecordDiff(zone_id));
  818. }
  819. TEST_F(SQLite3Update, addDiffWithoutUpdate) {
  820. // Right now we require startUpdateZone() prior to performing
  821. // addRecordDiff.
  822. copy(diff_begin_data, diff_begin_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  823. diff_params);
  824. EXPECT_THROW(accessor->addRecordDiff(0, getVersion(diff_begin_data),
  825. getOperation(diff_begin_data),
  826. diff_params),
  827. DataSourceError);
  828. // For now, we don't allow adding diffs in a general transaction either.
  829. accessor->startTransaction();
  830. EXPECT_THROW(accessor->addRecordDiff(0, getVersion(diff_begin_data),
  831. getOperation(diff_begin_data),
  832. diff_params),
  833. DataSourceError);
  834. }
  835. TEST_F(SQLite3Update, addDiffWithBadZoneID) {
  836. // For now, we require zone ID passed to addRecordDiff be equal to
  837. // that for the zone being updated.
  838. zone_id = accessor->startUpdateZone("example.com.", false).second;
  839. copy(diff_begin_data, diff_begin_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  840. diff_params);
  841. EXPECT_THROW(accessor->addRecordDiff(zone_id + 1,
  842. getVersion(diff_begin_data),
  843. getOperation(diff_begin_data),
  844. diff_params),
  845. DataSourceError);
  846. }
  847. TEST_F(SQLite3Update, addDiffRollback) {
  848. // Rollback tentatively added diffs. This is no different from the
  849. // update case, but we test it explicitly just in case.
  850. zone_id = accessor->startUpdateZone("example.com.", false).second;
  851. copy(diff_begin_data, diff_begin_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  852. diff_params);
  853. accessor->addRecordDiff(zone_id, getVersion(diff_begin_data),
  854. getOperation(diff_begin_data), diff_params);
  855. accessor->rollback();
  856. EXPECT_TRUE(accessor->getRecordDiff(zone_id).empty());
  857. }
  858. TEST_F(SQLite3Update, addDiffInBadOrder) {
  859. // At this level, the API is naive, and doesn't care if the diff sequence
  860. // is a valid IXFR order.
  861. zone_id = accessor->startUpdateZone("example.com.", false).second;
  862. // Add diff of 'end', then 'begin'
  863. copy(diff_end_data, diff_end_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  864. diff_params);
  865. accessor->addRecordDiff(zone_id, getVersion(diff_end_data),
  866. getOperation(diff_end_data), diff_params);
  867. copy(diff_begin_data, diff_begin_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  868. diff_params);
  869. accessor->addRecordDiff(zone_id, getVersion(diff_begin_data),
  870. getOperation(diff_begin_data), diff_params);
  871. accessor->commit();
  872. expected_stored.clear();
  873. expected_stored.push_back(diff_end_data);
  874. expected_stored.push_back(diff_begin_data);
  875. checkDiffs(expected_stored, accessor->getRecordDiff(zone_id));
  876. }
  877. TEST_F(SQLite3Update, addDiffWithUpdate) {
  878. // A more realistic example: add corresponding diffs while updating zone.
  879. // Implementation wise, there should be no reason this could fail if
  880. // the basic tests so far pass. But we check it in case we miss something.
  881. const char* const old_a_record[] = {
  882. "dns01.example.com.", "A", "192.0.2.1"
  883. };
  884. const char* const new_a_record[] = {
  885. "dns01.example.com.", "com.example.dns01.", "3600", "A", "",
  886. "192.0.2.10"
  887. };
  888. const char* const old_soa_record[] = {
  889. "example.com.", "SOA",
  890. "ns.example.com. admin.example.com. 1234 3600 1800 2419200 7200",
  891. };
  892. const char* const new_soa_record[] = {
  893. "dns01.example.com.", "com.example.dns01.", "3600", "A", "",
  894. "ns.example.com. admin.example.com. 1300 3600 1800 2419200 7200",
  895. };
  896. zone_id = accessor->startUpdateZone("example.com.", false).second;
  897. // Delete SOA (and add that diff)
  898. copy(old_soa_record, old_soa_record + DatabaseAccessor::DEL_PARAM_COUNT,
  899. del_params);
  900. accessor->deleteRecordInZone(del_params);
  901. copy(diff_begin_data, diff_begin_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  902. diff_params);
  903. accessor->addRecordDiff(zone_id, getVersion(diff_begin_data),
  904. getOperation(diff_begin_data), diff_params);
  905. // Delete A
  906. copy(old_a_record, old_a_record + DatabaseAccessor::DEL_PARAM_COUNT,
  907. del_params);
  908. accessor->deleteRecordInZone(del_params);
  909. copy(diff_del_a_data, diff_del_a_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  910. diff_params);
  911. accessor->addRecordDiff(zone_id, getVersion(diff_del_a_data),
  912. getOperation(diff_del_a_data), diff_params);
  913. // Add SOA
  914. copy(new_soa_record, new_soa_record + DatabaseAccessor::ADD_COLUMN_COUNT,
  915. add_columns);
  916. accessor->addRecordToZone(add_columns);
  917. copy(diff_end_data, diff_end_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  918. diff_params);
  919. accessor->addRecordDiff(zone_id, getVersion(diff_end_data),
  920. getOperation(diff_end_data), diff_params);
  921. // Add A
  922. copy(new_a_record, new_a_record + DatabaseAccessor::ADD_COLUMN_COUNT,
  923. add_columns);
  924. accessor->addRecordToZone(add_columns);
  925. copy(diff_add_a_data, diff_add_a_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  926. diff_params);
  927. accessor->addRecordDiff(zone_id, getVersion(diff_add_a_data),
  928. getOperation(diff_add_a_data), diff_params);
  929. accessor->commit();
  930. expected_stored.clear();
  931. expected_stored.push_back(diff_begin_data);
  932. expected_stored.push_back(diff_del_a_data);
  933. expected_stored.push_back(diff_end_data);
  934. expected_stored.push_back(diff_add_a_data);
  935. checkDiffs(expected_stored, accessor->getRecordDiff(zone_id));
  936. }
  937. TEST_F(SQLite3Update, addDiffWithNoTable) {
  938. // An attempt of adding diffs to an old version of database that doesn't
  939. // have a diffs table. This will fail in preparing the statement.
  940. initAccessor(SQLITE_DBFILE_EXAMPLE + ".nodiffs", "IN");
  941. zone_id = accessor->startUpdateZone("example.com.", false).second;
  942. copy(diff_begin_data, diff_begin_data + DatabaseAccessor::DIFF_PARAM_COUNT,
  943. diff_params);
  944. EXPECT_THROW(accessor->addRecordDiff(zone_id, getVersion(diff_begin_data),
  945. getOperation(diff_begin_data),
  946. diff_params),
  947. SQLite3Error);
  948. }
  949. } // end anonymous namespace