[svn] commit: r2508 - in /branches/trac232/src/lib/datasrc: ./ tests/ tests/testdata/
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Jul 14 15:46:31 UTC 2010
Author: jelte
Date: Wed Jul 14 15:46:31 2010
New Revision: 2508
Log:
initial attempt at updates, not fully rfc-correct yet, but enough to satisfy the initial tests (for every type of update in the rfc and every type of prerequisite).
Added:
branches/trac232/src/lib/datasrc/tests/testdata/update1.packet
branches/trac232/src/lib/datasrc/tests/testdata/update2.packet
branches/trac232/src/lib/datasrc/tests/testdata/update3.packet
branches/trac232/src/lib/datasrc/tests/testdata/update4.packet
branches/trac232/src/lib/datasrc/tests/testdata/update5.packet
branches/trac232/src/lib/datasrc/tests/testdata/update6.packet
branches/trac232/src/lib/datasrc/tests/testdata/update7.packet
Modified:
branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc
branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc
Modified: branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc (original)
+++ branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc Wed Jul 14 15:46:31 2010
@@ -974,11 +974,16 @@
std::cout << "[XX] query prepared, executing" << std::endl;
int result = sqlite3_step(query);
+ int deleted_rows = sqlite3_total_changes(dbparameters->db_);
sqlite3_reset(query);
if (result == SQLITE_DONE) {
- return DataSrc::SUCCESS;
+ if (deleted_rows > 0) {
+ return DataSrc::SUCCESS;
+ } else {
+ return DataSrc::ERROR;
+ }
} else {
std::cout << "[XX] sqlite3 del_rr error: " << result << std::endl;;
std::cout << "[XX] " << sqlite3_errmsg(dbparameters->db_) << std::endl;
@@ -1168,9 +1173,22 @@
static bool
equalRRsets(const RRsetPtr& a, const RRsetPtr& b) {
- std::string as = a->toText();
- std::string bs = b->toText();
- return (as == bs);
+ if (a->getName() != b->getName() ||
+ a->getClass() != b->getClass() ||
+ a->getType() != b->getType() ||
+ a->getRdataCount() != b->getRdataCount()) {
+ return false;
+ }
+ RdataIteratorPtr ita = a->getRdataIterator();
+ RdataIteratorPtr itb = b->getRdataIterator();
+ itb->first();
+ for (ita->first(); !ita->isLast(); ita->next()) {
+ if (ita->getCurrent().compare(itb->getCurrent()) != 0) {
+ return false;
+ }
+ itb->next();
+ }
+ return true;
}
// should we have this as a convenience function in DataSrc?
@@ -1180,12 +1198,32 @@
DataSrc::Result result;
uint32_t flags = 0;
- result = datasrc->findExactRRset(rrset->getName(), rrset->getClass(),
- rrset->getType(), rrset_list, flags, NULL);
- return ((result == DataSrc::SUCCESS) &&
- (rrset_list.size() == 1) &&
- equalRRsets(rrset, *(rrset_list.begin()))
- );
+ cout << "[XX] haveRRset called on " << rrset->toText() << endl;
+
+ if (rrset->getClass() == RRClass::ANY() || rrset->getClass() == RRClass::NONE()) {
+ result = datasrc->findExactRRset(rrset->getName(), RRClass::IN(),
+ rrset->getType(), rrset_list, flags, NULL);
+ } else {
+ result = datasrc->findExactRRset(rrset->getName(), rrset->getClass(),
+ rrset->getType(), rrset_list, flags, NULL);
+ }
+ if (result != DataSrc::SUCCESS || rrset_list.size() == 0) {
+ cout << "[XX] findExact result not SUCCESS or rrset_list.size 0" << endl;
+ cout << "[XX] size: " << rrset_list.size() << endl;
+ cout << "[XX] returning false" << endl;
+ return false;
+ }
+ if (rrset->getRdataCount() > 0) {
+ cout << "[XX] checking for completely equal" << endl;
+ cout << "[XX] want: " << rrset->toText() << endl;
+ cout << "[XX] have: " << (*(rrset_list.begin()))->toText() << endl;
+ cout << "[XX] returning: " << equalRRsets(rrset, *(rrset_list.begin())) << endl;
+ return equalRRsets(rrset, *(rrset_list.begin()));
+ } else {
+ cout << "[XX] rdata count for match 0, so we found it" << endl;
+ cout << "[XX] returning: " << ((*(rrset_list.begin()))->getRdataCount() > 0) << endl;
+ return ((*(rrset_list.begin()))->getRdataCount() > 0);
+ }
}
// TODO: this is a very general one, move to DataSrc?
@@ -1292,33 +1330,50 @@
it++) {
RRsetPtr cur_prereq = *it;
cout << "[XX] PREREQ: " << cur_prereq->toText() << endl;
+ cout << "[XX] count: " << cur_prereq->getRdataCount() << endl;
// should we check TTL too?
// zone class checked for IN right now, should be matched to actual zone class
if (cur_prereq->getRdataCount() == 0 &&
- cur_prereq->getClass() == isc::dns::RRClass::IN() &&
+ cur_prereq->getClass() == isc::dns::RRClass::ANY() &&
cur_prereq->getType() != isc::dns::RRType::ANY()) {
// RRset Exists, value independent prerequisite (2.4.1)
cout << "[XX] rrset exists (value independent)" << endl;
+ if (!haveRRset(this, cur_prereq)) {
+ return ERROR;
+ }
+ cout << "[XX] ok" << endl;
} else if (cur_prereq->getRdataCount() > 0 &&
cur_prereq->getClass() == isc::dns::RRClass::IN() &&
cur_prereq->getType() != isc::dns::RRType::ANY()) {
// RRset Exists, value dependent prerequisite (2.4.2)
cout << "[XX] rrset exists (value dependent)" << endl;
+ if (!haveRRset(this, cur_prereq)) {
+ return ERROR;
+ }
} else if (cur_prereq->getRdataCount() == 0 &&
cur_prereq->getClass() == isc::dns::RRClass::NONE() &&
cur_prereq->getType() != isc::dns::RRType::ANY()) {
// RRset does not exist, value independent prerequisite (2.4.3)
cout << "[XX] rrset does not exist" << endl;
+ if (haveRRset(this, cur_prereq)) {
+ return ERROR;
+ }
} else if (cur_prereq->getRdataCount() == 0 &&
cur_prereq->getClass() == isc::dns::RRClass::ANY() &&
cur_prereq->getType() == isc::dns::RRType::ANY()) {
// Name is in use (2.4.4)
cout << "[XX] name is in use" << endl;
+ if (!haveRRset(this, cur_prereq)) {
+ return ERROR;
+ }
} else if (cur_prereq->getRdataCount() == 0 &&
cur_prereq->getClass() == isc::dns::RRClass::NONE() &&
cur_prereq->getType() == isc::dns::RRType::ANY()) {
// Name is not in use (2.4.5)
cout << "[XX] name is not in use" << endl;
+ if (haveRRset(this, cur_prereq)) {
+ return ERROR;
+ }
}
}
@@ -1327,30 +1382,43 @@
it++) {
RRsetPtr cur_update = *it;
std::cout << "[XX] Update RR: " << cur_update->toText() << std::endl;
+ DataSrc::Result result;
if (cur_update->getRdataCount() > 0 &&
cur_update->getClass() == isc::dns::RRClass::IN() &&
cur_update->getType() != isc::dns::RRType::ANY()) {
// add to rrset (2.5.1)
cout << "[XX] add to rrset" << endl;
- addRRset(transaction, cur_update);
+ result = addRRset(transaction, cur_update);
+ if (result != DataSrc::SUCCESS) {
+ return result;
+ }
} else if (cur_update->getRdataCount() == 0 &&
cur_update->getClass() == isc::dns::RRClass::ANY() &&
cur_update->getType() != isc::dns::RRType::ANY()) {
// delete rrset (2.5.2)
cout << "[XX] delete rrset" << endl;
- delRRset(transaction, cur_update);
+ result = delRRset(transaction, cur_update);
+ if (result != DataSrc::SUCCESS) {
+ return result;
+ }
} else if (cur_update->getRdataCount() == 0 &&
cur_update->getClass() == isc::dns::RRClass::ANY() &&
cur_update->getType() == isc::dns::RRType::ANY()) {
// delete all rrsets for name (2.5.3)
cout << "[XX] delete all rrsets for name" << endl;
- delRRset(transaction, cur_update);
+ result = delRRset(transaction, cur_update);
+ if (result != DataSrc::SUCCESS) {
+ return result;
+ }
} else if (cur_update->getRdataCount() > 0 &&
cur_update->getClass() == isc::dns::RRClass::NONE() &&
cur_update->getType() != isc::dns::RRType::ANY()) {
// delete from rrset (2.5.4)
cout << "[XX] delete rr from rrset" << endl;
- delRRset(transaction, cur_update);
+ result = delRRset(transaction, cur_update);
+ if (result != DataSrc::SUCCESS) {
+ return result;
+ }
}
//(*it)++;
}
Modified: branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc (original)
+++ branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc Wed Jul 14 15:46:31 2010
@@ -1194,9 +1194,132 @@
}
+
+static QuestionPtr
+questionFromFile(ifstream& file)
+{
+ string s;
+ file >> s;
+ if (s == "") {
+ return QuestionPtr();
+ }
+ if (s.size() > 0 && s[0] == ';') {
+ std::string ignore_rest_of_line;
+ getline(file, ignore_rest_of_line);
+ return QuestionPtr();
+ }
+ Name n(s);
+ file >> s;
+ RRClass rrclass(s);
+ file >> s;
+ RRType rrtype(s);
+ string line;
+ getline(file, line);
+
+ QuestionPtr question(new Question(n, rrclass, rrtype));
+ return question;
+}
+
+static RRsetPtr
+rrsetFromFile(ifstream& file)
+{
+ string s;
+ file >> s;
+ if (s == "") {
+ return RRsetPtr();
+ }
+ if (s.size() > 0 && s[0] == ';') {
+ std::string ignore_rest_of_line;
+ getline(file, ignore_rest_of_line);
+ return RRsetPtr();
+ }
+ Name n(s);
+
+ file >> s;
+ RRTTL ttl(s);
+
+ file >> s;
+ std::cout << "[XX] CLASS: " << s << std::endl;
+ RRClass rrclass(0);
+ if (s == "ANY") {
+ rrclass = RRClass::ANY();
+ } else if (s == "NONE") {
+ rrclass = RRClass::NONE();
+ } else {
+ rrclass = RRClass(s);
+ }
+
+ file >> s;
+ std::cout << "[XX] TYPE: " << s << std::endl;
+ RRType rrtype(0);
+ if (s == "ANY") {
+ rrtype = RRType::ANY();
+ } else {
+ rrtype = RRType(s);
+ }
+
+ RRsetPtr rrset = RRsetPtr(new RRset(n,
+ rrclass,
+ rrtype,
+ ttl));
+ string line;
+ getline(file, line);
+ while (line[0] == ' ' || line[0] == '\t') {
+ line.erase(0, 1);
+ }
+
+ if (line != "") {
+ std::cout << "[XX] RDATA LINE: '" << line << "'" << std::endl;
+ RdataPtr rdata = createRdata(rrtype, rrclass, line);
+ rrset->addRdata(rdata);
+ }
+ return rrset;
+}
+
// initialize the message with flags and codes,
// read a list of rrs and put them in that order in the answer
// section of the given message
+
+// reads rrsets from the given file into the given section
+// stops at eof or if empty line or line starting with ; is
+// read
+// returns 1 if empty line/comment has been seen
+// returns 0 if eof reached
+
+int
+rrsetsFromFile(ifstream& file, Message& msg, Section section)
+{
+ RRsetPtr prev_rrset = RRsetPtr();
+ while (! file.eof() ) {
+ RRsetPtr rrset = rrsetFromFile(file);
+ if (!rrset) {
+ if (prev_rrset) {
+ msg.addRRset(section, prev_rrset);
+ }
+ return 1;
+ }
+ if (prev_rrset) {
+ if (rrset) {
+ if (prev_rrset->getName() == rrset->getName() &&
+ prev_rrset->getType() == rrset->getType() &&
+ prev_rrset->getType() != RRType::SOA() &&
+ prev_rrset->getClass() == rrset->getClass()) {
+ RdataIteratorPtr it = rrset->getRdataIterator();
+ for (it->first(); !it->isLast(); it->next()) {
+ prev_rrset->addRdata(it->getCurrent());
+ }
+ rrset = RRsetPtr();
+ }
+ }
+ msg.addRRset(section, prev_rrset);
+ prev_rrset = rrset;
+ } else {
+ prev_rrset = rrset;
+ }
+ }
+ return 0;
+}
+
static int
ixfrFromFile(Message& m, const char* file_name) {
ifstream myfile(file_name);
@@ -1207,31 +1330,41 @@
m.setOpcode(isc::dns::Opcode::QUERY());
m.setRcode(isc::dns::Rcode::NOERROR());
if (myfile.is_open()) {
+ rrsetsFromFile(myfile, m, Section::ANSWER());
+ } else {
+ return -1;
+ }
+ cout << "[XX] CREATED IXFR PACKET:" << endl;
+ cout << m.toText() << endl;
+ return 0;
+}
+
+static int
+updateFromFile(Message& m, const char* file_name) {
+ ifstream myfile(file_name);
+
+ m.clear(Message::RENDER);
+ m.setQid(1234);
+ m.setOpcode(isc::dns::Opcode::UPDATE());
+ m.setRcode(isc::dns::Rcode::NOERROR());
+ int stage = 1;
+ QuestionPtr question;
+ if (myfile.is_open()) {
while (! myfile.eof() ) {
- string s;
- myfile >> s;
- if (s == "") {
- continue;
+ switch (stage) {
+ case 1:
+ question = questionFromFile(myfile);
+ if (question) {
+ m.addQuestion(question);
+ } else {
+ stage++;
+ }
+ break;
+ case 2:
+ rrsetsFromFile(myfile, m, Section::ANSWER());
+ rrsetsFromFile(myfile, m, Section::AUTHORITY());
+ rrsetsFromFile(myfile, m, Section::ADDITIONAL());
}
- Name n(s);
- myfile >> s;
- RRTTL ttl(s);
- myfile >> s;
- RRClass rrclass(s);
- myfile >> s;
- RRType rrtype(s);
- string line;
- getline(myfile, line);
- while (line[0] == ' ' || line[0] == '\t') {
- line.erase(0, 1);
- }
- RdataPtr rdata = createRdata(rrtype, rrclass, line);
- RRsetPtr rrset = RRsetPtr(new RRset(n,
- rrclass,
- rrtype,
- ttl));
- rrset->addRdata(rdata);
- m.addRRset(Section::ANSWER(), rrset, false);
}
} else {
return -1;
@@ -1377,12 +1510,6 @@
ASSERT_EQ(DataSrc::ERROR, data_source.doUpdate(transaction1, update_msg));
// removeQuestion not implemented, reset msg
- update_msg.clear(Message::RENDER);
- update_msg.setQid(1234);
- update_msg.setOpcode(isc::dns::Opcode::UPDATE());
- QuestionPtr question(new Question(Name("example.com"), RRClass::IN(), RRType::SOA()));
- update_msg.addQuestion(question);
-
// checks, we delete one set, one name, one rr, add a set, and add to a set
// delete ip46 A rrset
// delete all from www.example.com
@@ -1411,40 +1538,7 @@
,
Name("example.com"), RRClass::IN(), RRType::NS());
- RRsetPtr delete_a_record(new RRset(Name("ip46.example.com."),
- RRClass::ANY(),
- RRType::A(),
- RRTTL(3600)));
- //delete_a_record->addRdata(createRdata(RRType::A(), RRClass::IN(), "192.0.3.1"));
- update_msg.addRRset(Section::AUTHORITY(), delete_a_record, false);
-
- RRsetPtr delete_all_www(new RRset(Name("www.example.com."),
- RRClass::ANY(),
- RRType::ANY(),
- RRTTL(0)));
- update_msg.addRRset(Section::AUTHORITY(), delete_all_www, false);
-
- RRsetPtr delete_mx_rr(new RRset(Name("example.com."),
- RRClass::NONE(),
- RRType::MX(),
- RRTTL(0)));
- delete_mx_rr->addRdata(createRdata(RRType::MX(), RRClass::IN(), "10 mail.example.com."));
- update_msg.addRRset(Section::AUTHORITY(), delete_mx_rr, false);
-
- RRsetPtr add_newaddr_rr(new RRset(Name("newaddr.example.com."),
- RRClass::IN(),
- RRType::A(),
- RRTTL(3600)));
- add_newaddr_rr->addRdata(createRdata(RRType::A(), RRClass::IN(), "192.0.2.12"));
- update_msg.addRRset(Section::AUTHORITY(), add_newaddr_rr, false);
-
- RRsetPtr add_ns_rr(new RRset(Name("example.com."),
- RRClass::IN(),
- RRType::NS(),
- RRTTL(3600)));
- add_ns_rr->addRdata(createRdata(RRType::NS(), RRClass::IN(), "dns04.example.com."));
- update_msg.addRRset(Section::AUTHORITY(), add_ns_rr, false);
-
+ ASSERT_EQ(0, updateFromFile(update_msg, TEST_DATA_DIR "/update1.packet"));
ASSERT_EQ(DataSrc::SUCCESS, data_source.doUpdate(transaction1, update_msg));
data_source.commitTransaction(transaction1);
@@ -1470,4 +1564,52 @@
}
-}
+TEST_F(Sqlite3DataSourceTest, dynamic_update_prereq_fails) {
+ // reset database
+ ASSERT_EQ(0, install_writable_database());
+
+ // use our copied writable datasource db
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.close());
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.init(SQLITE_DBFILE_WRITE));
+
+ Message update_msg(Message::RENDER);
+
+ DataSrcTransaction transaction1(&data_source, zone_name);
+ data_source.startTransaction(transaction1);
+
+ ASSERT_EQ(0, updateFromFile(update_msg, TEST_DATA_DIR "/update2.packet"));
+ ASSERT_EQ(DataSrc::ERROR, data_source.doUpdate(transaction1, update_msg));
+
+ ASSERT_EQ(0, updateFromFile(update_msg, TEST_DATA_DIR "/update3.packet"));
+ ASSERT_EQ(DataSrc::ERROR, data_source.doUpdate(transaction1, update_msg));
+
+ ASSERT_EQ(0, updateFromFile(update_msg, TEST_DATA_DIR "/update4.packet"));
+ ASSERT_EQ(DataSrc::ERROR, data_source.doUpdate(transaction1, update_msg));
+
+ ASSERT_EQ(0, updateFromFile(update_msg, TEST_DATA_DIR "/update5.packet"));
+ ASSERT_EQ(DataSrc::ERROR, data_source.doUpdate(transaction1, update_msg));
+
+ ASSERT_EQ(0, updateFromFile(update_msg, TEST_DATA_DIR "/update6.packet"));
+ ASSERT_EQ(DataSrc::ERROR, data_source.doUpdate(transaction1, update_msg));
+
+}
+
+TEST_F(Sqlite3DataSourceTest, dynamic_update_bad_update) {
+ // reset database
+ ASSERT_EQ(0, install_writable_database());
+
+ // use our copied writable datasource db
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.close());
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.init(SQLITE_DBFILE_WRITE));
+
+ Message update_msg(Message::RENDER);
+
+ DataSrcTransaction transaction1(&data_source, zone_name);
+ data_source.startTransaction(transaction1);
+
+ ASSERT_EQ(0, updateFromFile(update_msg, TEST_DATA_DIR "/update7.packet"));
+ ASSERT_EQ(DataSrc::ERROR, data_source.doUpdate(transaction1, update_msg));
+
+}
+
+}
More information about the bind10-changes
mailing list