[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