Browse Source

[2973] added a test to create many zones using ZoneWriter with mapped segment.

it actually revealed a bug, which will be fixed in subsequent commits.
JINMEI Tatuya 12 years ago
parent
commit
65b0c0b8a2

+ 1 - 0
src/lib/datasrc/tests/memory/testdata/Makefile.am

@@ -29,6 +29,7 @@ EXTRA_DIST += example.org-rrsigs.zone
 EXTRA_DIST += example.org-wildcard-dname.zone
 EXTRA_DIST += example.org-wildcard-ns.zone
 EXTRA_DIST += example.org-wildcard-nsec3.zone
+EXTRA_DIST += template.zone
 EXTRA_DIST += rrset-collection.zone
 
 EXTRA_DIST += 2503-test.zone

+ 4 - 0
src/lib/datasrc/tests/memory/testdata/template.zone

@@ -0,0 +1,4 @@
+; a zone file that can be used with any origin.
+
+@ 3600 IN SOA . . 1 0 0 0 0
+@ 3600 IN NS ns1

+ 87 - 0
src/lib/datasrc/tests/memory/zone_writer_unittest.cc

@@ -12,10 +12,20 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <config.h>
+
 #include <datasrc/memory/zone_writer.h>
 #include <datasrc/memory/zone_table_segment_local.h>
 #include <datasrc/memory/zone_data.h>
+#include <datasrc/memory/zone_data_loader.h>
+#include <datasrc/memory/load_action.h>
+#include <datasrc/memory/zone_table.h>
 #include <datasrc/exceptions.h>
+#include <datasrc/result.h>
+
+#include <util/memory_segment_mapped.h>
+
+#include <cc/data.h>
 
 #include <dns/rrclass.h>
 #include <dns/name.h>
@@ -27,8 +37,10 @@
 
 #include <boost/scoped_ptr.hpp>
 #include <boost/bind.hpp>
+#include <boost/format.hpp>
 
 #include <string>
+#include <unistd.h>
 
 using boost::scoped_ptr;
 using boost::bind;
@@ -325,4 +337,79 @@ TEST_F(ZoneWriterTest, autoCleanUp) {
     EXPECT_NO_THROW(writer_->load());
 }
 
+// Used in the manyWrites test, encapsulating loadZoneData() to avoid
+// its signature ambiguity.
+ZoneData*
+loadZoneDataWrapper(isc::util::MemorySegment& segment, const RRClass& rrclass,
+                    const Name& name, const std::string& filename)
+{
+    return (loadZoneData(segment, rrclass, name, filename));
+}
+
+// Check the behavior of creating many small zones.  The main purpose of
+// test is to trigger MemorySegmentGrown exception in ZoneWriter::install.
+// There's no easy (if any) way to cause that reliably as it's highly
+// dependent on details of the underlying boost implementation and probably
+// also on the system behavior, but we'll try some promising scenario (it
+// in fact triggered the intended result at least on one environment).
+TEST_F(ZoneWriterTest, manyWrites) {
+#ifdef USE_SHARED_MEMORY
+    // First, make a fresh mapped file of a small size (so it'll be more likely
+    // to grow in the test.
+    const char* const mapped_file = TEST_DATA_BUILDDIR "/test.mapped";
+    unlink(mapped_file);
+    boost::scoped_ptr<isc::util::MemorySegmentMapped> segment(
+        new isc::util::MemorySegmentMapped(
+            mapped_file, isc::util::MemorySegmentMapped::CREATE_ONLY, 4096));
+    segment.reset();
+
+    // Then prepare a ZoneTableSegment of the 'mapped' type specifying the
+    // file we just created.
+    boost::scoped_ptr<ZoneTableSegment> zt_segment(
+        ZoneTableSegment::create(RRClass::IN(), "mapped"));
+    const isc::data::ConstElementPtr params =
+        isc::data::Element::fromJSON(
+            "{\"mapped-file\": \"" + std::string(mapped_file) + "\"}");
+    zt_segment->reset(ZoneTableSegment::READ_WRITE, params);
+#else
+    // Do the same test for the local segment, although there shouldn't be
+    // anything tricky in that case.
+    boost::scoped_ptr<ZoneTableSegment> zt_segment(
+        ZoneTableSegment::create(RRClass::IN(), "local"));
+#endif
+
+    // Now, create many small zones in the zone table with a ZoneWriter.
+    // We use larger origin names so it'll (hopefully) require the memory
+    // segment to grow while adding the name into the internal table.
+    const size_t zone_count = 10000; // arbitrary choice
+    for (size_t i = 0; i < zone_count; ++i) {
+        const Name origin(
+            boost::str(boost::format("%063u.%063u.%063u.example.org")
+                       % i % i % i));
+        const LoadAction action = boost::bind(loadZoneDataWrapper, _1,
+                                              RRClass::IN(), origin,
+                                              TEST_DATA_DIR
+                                              "/template.zone");
+        ZoneWriter writer(*zt_segment, action, origin, RRClass::IN(), false);
+        writer.load();
+        writer.install();
+        writer.cleanup();
+
+        // Confirm it's been successfully added and can be actually found.
+        const ZoneTable::FindResult result =
+            zt_segment->getHeader().getTable()->findZone(origin);
+        EXPECT_EQ(isc::datasrc::result::SUCCESS, result.code);
+        EXPECT_NE(static_cast<const ZoneData*>(NULL), result.zone_data) <<
+            "unexpected find result: " + origin.toText();
+    }
+
+    // Make sure to close the segment before (possibly) removing the mapped
+    // file.
+    zt_segment.reset();
+
+#ifdef USE_SHARED_MEMORY
+    unlink(mapped_file);
+#endif
+}
+
 }