BIND 10 trac2850_2, updated. 9784a1841ff7a5f08c92a0c646bbc4ff9a0b4ccb [2850] Add tests for the various open modes
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon May 6 06:43:21 UTC 2013
The branch, trac2850_2 has been updated
via 9784a1841ff7a5f08c92a0c646bbc4ff9a0b4ccb (commit)
via 5082c255bbeb8c83f9ab08d4e28429cc271b2fec (commit)
via 3599c07417b1bcf40ae8e59959278b4a59ede827 (commit)
via 043b3d2952712cd61e7ffb4f73f3253d11ce6bd2 (commit)
via b5cd040334461d9f5ab0f1267d505bc7ac3e0ca9 (commit)
via 54a1d02e8816b53e0d4ab77817380946ddf156d4 (commit)
from 7d1a2ca88d0daac2779ecccf50c4308eb0914ebd (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 9784a1841ff7a5f08c92a0c646bbc4ff9a0b4ccb
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon May 6 12:12:59 2013 +0530
[2850] Add tests for the various open modes
commit 5082c255bbeb8c83f9ab08d4e28429cc271b2fec
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon May 6 11:37:14 2013 +0530
[2850] Constify getNamedAddress()
commit 3599c07417b1bcf40ae8e59959278b4a59ede827
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon May 6 11:17:17 2013 +0530
[2850] Add a way to pass a seed to the random number generator
commit 043b3d2952712cd61e7ffb4f73f3253d11ce6bd2
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon May 6 11:14:04 2013 +0530
[2850] Make minor coding style fixes
commit b5cd040334461d9f5ab0f1267d505bc7ac3e0ca9
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon May 6 11:13:33 2013 +0530
[2850] Include dependency header in random_number_generator.h itself
commit 54a1d02e8816b53e0d4ab77817380946ddf156d4
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon May 6 11:12:07 2013 +0530
[2850] Make a minor comment update
-----------------------------------------------------------------------
Summary of changes:
.../memory/zone_table_segment_mapped_unittest.cc | 141 +++++++++++++++++++-
src/lib/util/memory_segment.h | 10 +-
src/lib/util/memory_segment_local.cc | 5 +-
src/lib/util/memory_segment_local.h | 2 +-
src/lib/util/memory_segment_mapped.cc | 2 +-
src/lib/util/memory_segment_mapped.h | 2 +-
src/lib/util/random/random_number_generator.h | 10 +-
.../util/tests/random_number_generator_unittest.cc | 28 +++-
8 files changed, 183 insertions(+), 17 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/tests/memory/zone_table_segment_mapped_unittest.cc b/src/lib/datasrc/tests/memory/zone_table_segment_mapped_unittest.cc
index e13a3e6..86718e9 100644
--- a/src/lib/datasrc/tests/memory/zone_table_segment_mapped_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_table_segment_mapped_unittest.cc
@@ -14,15 +14,20 @@
#include <datasrc/memory/zone_writer.h>
#include <datasrc/memory/zone_table_segment_mapped.h>
+#include <util/random/random_number_generator.h>
+#include <util/unittests/check_valgrind.h>
#include <gtest/gtest.h>
#include <boost/scoped_ptr.hpp>
#include <boost/interprocess/file_mapping.hpp>
+#include <sys/stat.h>
+
using namespace isc::dns;
using namespace isc::datasrc::memory;
using namespace isc::data;
using namespace isc::util;
+using namespace isc::util::random;
using namespace std;
using boost::scoped_ptr;
@@ -55,6 +60,56 @@ protected:
const ConstElementPtr config_params_;
};
+bool
+fileExists(const char* path) {
+ struct stat sb;
+ const int status = stat(path, &sb);
+ if (status != 0) {
+ EXPECT_EQ(ENOENT, errno);
+ return (false);
+ }
+ return (true);
+}
+
+void
+createData(MemorySegment& segment) {
+ // For purposes of this test, we assume that the following
+ // allocations do not resize the mapped segment. For this, we have
+ // to keep the size of test data reasonably small.
+ UniformRandomIntegerGenerator gen(0, INT_MAX, getpid());
+ for (int i = 0; i < 256; ++i) {
+ string name("name");
+ name += i;
+ const int value = gen();
+ void* ptr = segment.allocate(sizeof (int));
+ ASSERT_TRUE(ptr);
+ *static_cast<int*>(ptr) = value;
+ const bool grew = segment.setNamedAddress(name.c_str(), ptr);
+ ASSERT_FALSE(grew);
+ }
+}
+
+bool
+verifyData(const MemorySegment& segment) {
+ UniformRandomIntegerGenerator gen(0, INT_MAX, getpid());
+ for (int i = 0; i < 256; ++i) {
+ string name("name");
+ name += i;
+ const int value = gen();
+ const MemorySegment::NamedAddressResult result =
+ segment.getNamedAddress(name.c_str());
+ if (!result.first) {
+ return (false);
+ }
+ if (*static_cast<int*>(result.second) != value) {
+ return (false);
+ }
+ }
+
+ return (true);
+}
+
+
TEST_F(ZoneTableSegmentMappedTest, getHeaderUninitialized) {
// This should throw as we haven't called reset() yet.
EXPECT_THROW(ztable_segment_->getHeader(), isc::InvalidOperation);
@@ -170,8 +225,92 @@ TEST_F(ZoneTableSegmentMappedTest, reset) {
EXPECT_TRUE(ztable_segment_->isWritable());
}
+TEST_F(ZoneTableSegmentMappedTest, resetCreate) {
+ // At this point, the underlying file must not exist.
+ ASSERT_FALSE(fileExists(mapped_file));
+
+ // Open the underlying mapped file in create mode.
+ ztable_segment_->reset(ZoneTableSegment::CREATE, config_params_);
+
+ ASSERT_TRUE(ztable_segment_->isWritable());
+
+ // Create the data.
+ createData(ztable_segment_->getMemorySegment());
+ EXPECT_TRUE(verifyData(ztable_segment_->getMemorySegment()));
+
+ // Close the segment.
+ ztable_segment_->clear();
+
+ // At this point, the underlying file must still exist.
+ ASSERT_TRUE(fileExists(mapped_file));
+
+ // Open the underlying mapped file in create mode again.
+ ztable_segment_->reset(ZoneTableSegment::CREATE, config_params_);
+
+ // The old data should be gone.
+ EXPECT_FALSE(verifyData(ztable_segment_->getMemorySegment()));
+}
+
+TEST_F(ZoneTableSegmentMappedTest, resetReadWrite) {
+ // At this point, the underlying file must not exist.
+ ASSERT_FALSE(fileExists(mapped_file));
+
+ // Open the underlying mapped file in read+write mode.
+ ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
+
+ ASSERT_TRUE(ztable_segment_->isWritable());
+
+ // Create the data.
+ createData(ztable_segment_->getMemorySegment());
+ EXPECT_TRUE(verifyData(ztable_segment_->getMemorySegment()));
+
+ // Close the segment.
+ ztable_segment_->clear();
+
+ // At this point, the underlying file must still exist.
+ ASSERT_TRUE(fileExists(mapped_file));
+
+ // Open the underlying mapped file in read+write mode again.
+ ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
+
+ // The old data should still be available.
+ EXPECT_TRUE(verifyData(ztable_segment_->getMemorySegment()));
+}
+
+TEST_F(ZoneTableSegmentMappedTest, resetReadOnly) {
+ // At this point, the underlying file must not exist.
+ ASSERT_FALSE(fileExists(mapped_file));
+
+ // Open the underlying mapped file in read+write mode.
+ ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
+
+ ASSERT_TRUE(ztable_segment_->isWritable());
+
+ // Create the data.
+ createData(ztable_segment_->getMemorySegment());
+ EXPECT_TRUE(verifyData(ztable_segment_->getMemorySegment()));
+
+ // Close the segment.
+ ztable_segment_->clear();
+
+ // At this point, the underlying file must still exist.
+ ASSERT_TRUE(fileExists(mapped_file));
+
+ // Open the underlying mapped file in read-only mode again.
+ ztable_segment_->reset(ZoneTableSegment::READ_ONLY, config_params_);
+
+ // The old data should still be available.
+ EXPECT_TRUE(verifyData(ztable_segment_->getMemorySegment()));
+
+ // But trying to allocate new data should result in an exception as
+ // the segment is read-only!
+ EXPECT_THROW(createData(ztable_segment_->getMemorySegment()),
+ MemorySegmentError);
+}
+
TEST_F(ZoneTableSegmentMappedTest, clear) {
- // First, load an underlying mapped file
+ // First, open an underlying mapped file in read+write mode (doesn't
+ // exist yet)
ztable_segment_->reset(ZoneTableSegment::READ_WRITE,
config_params_);
diff --git a/src/lib/util/memory_segment.h b/src/lib/util/memory_segment.h
index 44b9560..a93b5ad 100644
--- a/src/lib/util/memory_segment.h
+++ b/src/lib/util/memory_segment.h
@@ -118,6 +118,8 @@ public:
/// requested storage.
/// \throw MemorySegmentGrown The memory segment doesn't have sufficient
/// space for the requested size and has grown internally.
+ /// \throw MemorySegmentError An attempt was made to allocate
+ /// storage on a read-only memory segment.
///
/// \param size The size of the memory requested in bytes.
/// \return Returns pointer to the memory allocated.
@@ -178,8 +180,8 @@ public:
/// as \c addr even if it wouldn't be considered to "belong to" the
/// segment in its normal sense; it can be used to indicate that memory
/// has not been allocated for the specified name. A subsequent call
- /// to \c getNamedAddress() will return std::pair (true, NULL) for
- /// that name.
+ /// to \c getNamedAddress() will return NamedAddressResult(true, NULL)
+ /// for that name.
///
/// \note Naming an address is intentionally separated from allocation
/// so that, for example, one module of a program can name a memory
@@ -254,7 +256,7 @@ public:
/// \return An std::pair containing a bool (set to true if the name
/// was found, or false otherwise) and the address associated with
/// the name (which is undefined if the name was not found).
- NamedAddressResult getNamedAddress(const char* name) {
+ NamedAddressResult getNamedAddress(const char* name) const {
// This public method implements common validation. The actual
// work specific to the derived segment is delegated to the
// corresponding protected method.
@@ -296,7 +298,7 @@ protected:
virtual bool setNamedAddressImpl(const char* name, void* addr) = 0;
/// \brief Implementation of getNamedAddress beyond common validation.
- virtual NamedAddressResult getNamedAddressImpl(const char* name) = 0;
+ virtual NamedAddressResult getNamedAddressImpl(const char* name) const = 0;
/// \brief Implementation of clearNamedAddress beyond common validation.
virtual bool clearNamedAddressImpl(const char* name) = 0;
diff --git a/src/lib/util/memory_segment_local.cc b/src/lib/util/memory_segment_local.cc
index e68db27..b81fe5e 100644
--- a/src/lib/util/memory_segment_local.cc
+++ b/src/lib/util/memory_segment_local.cc
@@ -52,8 +52,9 @@ MemorySegmentLocal::allMemoryDeallocated() const {
}
MemorySegment::NamedAddressResult
-MemorySegmentLocal::getNamedAddressImpl(const char* name) {
- std::map<std::string, void*>::iterator found = named_addrs_.find(name);
+MemorySegmentLocal::getNamedAddressImpl(const char* name) const {
+ std::map<std::string, void*>::const_iterator found =
+ named_addrs_.find(name);
if (found != named_addrs_.end()) {
return (NamedAddressResult(true, found->second));
}
diff --git a/src/lib/util/memory_segment_local.h b/src/lib/util/memory_segment_local.h
index 90d4907..de7249e 100644
--- a/src/lib/util/memory_segment_local.h
+++ b/src/lib/util/memory_segment_local.h
@@ -70,7 +70,7 @@ public:
///
/// There's a small chance this method could throw std::bad_alloc.
/// It should be considered a fatal error.
- virtual NamedAddressResult getNamedAddressImpl(const char* name);
+ virtual NamedAddressResult getNamedAddressImpl(const char* name) const;
/// \brief Local segment version of setNamedAddress.
///
diff --git a/src/lib/util/memory_segment_mapped.cc b/src/lib/util/memory_segment_mapped.cc
index ca9c9c6..f53306b 100644
--- a/src/lib/util/memory_segment_mapped.cc
+++ b/src/lib/util/memory_segment_mapped.cc
@@ -280,7 +280,7 @@ MemorySegmentMapped::allMemoryDeallocated() const {
}
MemorySegment::NamedAddressResult
-MemorySegmentMapped::getNamedAddressImpl(const char* name) {
+MemorySegmentMapped::getNamedAddressImpl(const char* name) const {
offset_ptr<void>* storage =
impl_->base_sgmt_->find<offset_ptr<void> >(name).first;
if (storage) {
diff --git a/src/lib/util/memory_segment_mapped.h b/src/lib/util/memory_segment_mapped.h
index 6798210..492cf86 100644
--- a/src/lib/util/memory_segment_mapped.h
+++ b/src/lib/util/memory_segment_mapped.h
@@ -195,7 +195,7 @@ public:
/// \brief Mapped segment version of getNamedAddress.
///
/// This version never throws.
- virtual NamedAddressResult getNamedAddressImpl(const char* name);
+ virtual NamedAddressResult getNamedAddressImpl(const char* name) const;
/// \brief Mapped segment version of clearNamedAddress.
///
diff --git a/src/lib/util/random/random_number_generator.h b/src/lib/util/random/random_number_generator.h
index f0c0fb3..3f2a907 100644
--- a/src/lib/util/random/random_number_generator.h
+++ b/src/lib/util/random/random_number_generator.h
@@ -18,6 +18,7 @@
#include <algorithm>
#include <cmath>
#include <numeric>
+#include <vector>
#include <exceptions/exceptions.h>
@@ -59,7 +60,9 @@ public:
///
/// \param min The minimum number in the range
/// \param max The maximum number in the range
- UniformRandomIntegerGenerator(int min, int max):
+ /// \param seed A seed for the RNG. If 0 is passed, the current time
+ /// is used.
+ UniformRandomIntegerGenerator(int min, int max, unsigned int seed = 0):
min_(std::min(min, max)), max_(std::max(min, max)),
dist_(min_, max_), generator_(rng_, dist_)
{
@@ -72,7 +75,10 @@ public:
}
// Init with the current time
- rng_.seed(time(NULL));
+ if (seed == 0) {
+ seed = time(NULL);
+ }
+ rng_.seed(seed);
}
/// \brief Generate uniformly distributed integer
diff --git a/src/lib/util/tests/random_number_generator_unittest.cc b/src/lib/util/tests/random_number_generator_unittest.cc
index 23d5b88..195f163 100644
--- a/src/lib/util/tests/random_number_generator_unittest.cc
+++ b/src/lib/util/tests/random_number_generator_unittest.cc
@@ -14,14 +14,16 @@
#include <config.h>
+#include <util/random/random_number_generator.h>
+
#include <gtest/gtest.h>
#include <boost/shared_ptr.hpp>
-#include <algorithm>
#include <iostream>
-#include <vector>
+#include <climits>
-#include <util/random/random_number_generator.h>
+#include <sys/types.h>
+#include <unistd.h>
namespace isc {
namespace util {
@@ -82,7 +84,22 @@ TEST_F(UniformRandomIntegerGeneratorTest, IntegerRange) {
vector<int>::iterator it = unique(numbers.begin(), numbers.end());
// make sure the numbers are in range [min, max]
- ASSERT_EQ(it - numbers.begin(), max() - min() + 1);
+ ASSERT_EQ(it - numbers.begin(), max() - min() + 1);
+}
+
+TEST_F(UniformRandomIntegerGeneratorTest, withSeed) {
+ // Test that two generators with the same seed return the same
+ // sequence.
+ UniformRandomIntegerGenerator gen1(0, INT_MAX, getpid());
+ vector<int> numbers;
+ for (int i = 0; i < 1024; ++i) {
+ numbers.push_back(gen1());
+ }
+
+ UniformRandomIntegerGenerator gen2(0, INT_MAX, getpid());
+ for (int i = 0; i < 1024; ++i) {
+ EXPECT_EQ(numbers[i], gen2());
+ }
}
/// \brief Test Fixture Class for weighted random number generator
@@ -99,7 +116,8 @@ public:
TEST_F(WeightedRandomIntegerGeneratorTest, Constructor) {
vector<double> probabilities;
- // If no probabilities is provided, the smallest integer will always be generated
+ // If no probabilities is provided, the smallest integer will always
+ // be generated
WeightedRandomIntegerGenerator gen(probabilities, 123);
for (int i = 0; i < 100; ++i) {
ASSERT_EQ(gen(), 123);
More information about the bind10-changes
mailing list