From ca7de05e62020126aa7d3ec361ec2f69f896dc32 Mon Sep 17 00:00:00 2001 From: Heinz Mauelshagen Date: Wed, 23 Jan 2013 14:32:03 +0100 Subject: [PATCH 1/3] buffer_t.cc: more tests --- persistent-data/buffer.h | 8 ++++---- unit-tests/buffer_t.cc | 12 ++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/persistent-data/buffer.h b/persistent-data/buffer.h index 5f35cd8..45e2390 100644 --- a/persistent-data/buffer.h +++ b/persistent-data/buffer.h @@ -32,19 +32,19 @@ //---------------------------------------------------------------- namespace persistent_data { - // Joe has buffer<> in other parts of the code, so... uint32_t const DEFAULT_BUFFER_SIZE = 4096; // Allocate buffer of Size with Alignment imposed. // - // Allocation needs to be on the heap in order to provide alignment guarantees! - // + // Allocation needs to be on the heap in order to provide alignment + // guarantees. + // // Alignment must be a power of two. - template class buffer : private boost::noncopyable { public: typedef boost::shared_ptr ptr; + typedef boost::shared_ptr const_ptr; unsigned char &operator[](unsigned index) { check_index(index); diff --git a/unit-tests/buffer_t.cc b/unit-tests/buffer_t.cc index 248ad0a..a5d98a5 100644 --- a/unit-tests/buffer_t.cc +++ b/unit-tests/buffer_t.cc @@ -82,12 +82,20 @@ BOOST_AUTO_TEST_CASE(buffer_8_a_8_access) BOOST_CHECK_EQUAL((*b)[0], '\0'); } +BOOST_AUTO_TEST_CASE(buffer_8_a_8_oob) +{ + uint32_t const sz = 8, align = 8; + buffer::ptr b = create_buffer(); + + BOOST_CHECK_NO_THROW((*b)[8] = 0); +} + BOOST_AUTO_TEST_CASE(buffer_8_a_8_const_access) { uint32_t const sz = 8, align = 8; - buffer::ptr const b = create_buffer(); + buffer::const_ptr b = create_buffer(); - (*b)[0] = 0; // Compile time error accessing read-only location + // (*b)[0] = 0; // Compile time error accessing read-only location } // 8 byte buffer size, varying alignment from 1 - 7 From dc06c88758560f6c7f320fbddc3d6424c2c1249e Mon Sep 17 00:00:00 2001 From: Heinz Mauelshagen Date: Wed, 23 Jan 2013 14:39:42 +0100 Subject: [PATCH 2/3] Joe's BOOST_STATIC_ASSERT addition --- persistent-data/buffer.h | 10 +++++++++- unit-tests/buffer_t.cc | 15 +++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/persistent-data/buffer.h b/persistent-data/buffer.h index 45e2390..051db59 100644 --- a/persistent-data/buffer.h +++ b/persistent-data/buffer.h @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -43,6 +44,9 @@ namespace persistent_data { template class buffer : private boost::noncopyable { public: + BOOST_STATIC_ASSERT_MSG((Alignment > 1) & !(Alignment & (Alignment - 1)), + "Alignment must be a power of two."); + typedef boost::shared_ptr ptr; typedef boost::shared_ptr const_ptr; @@ -73,7 +77,11 @@ namespace persistent_data { // Allocates size bytes and returns a pointer to the // allocated memory. The memory address will be a // multiple of 'Alignment', which must be a power of two - return memalign(Alignment, s); + void *mem = memalign(Alignment, s); + if (!mem) + throw std::bad_alloc(); + + return mem; } static void operator delete(void *p) { diff --git a/unit-tests/buffer_t.cc b/unit-tests/buffer_t.cc index a5d98a5..382b4da 100644 --- a/unit-tests/buffer_t.cc +++ b/unit-tests/buffer_t.cc @@ -79,24 +79,18 @@ BOOST_AUTO_TEST_CASE(buffer_8_a_8_access) buffer::ptr b = create_buffer(); (*b)[0] = 0; - BOOST_CHECK_EQUAL((*b)[0], '\0'); -} - -BOOST_AUTO_TEST_CASE(buffer_8_a_8_oob) -{ - uint32_t const sz = 8, align = 8; - buffer::ptr b = create_buffer(); - - BOOST_CHECK_NO_THROW((*b)[8] = 0); + BOOST_CHECK_EQUAL((*b)[0], 0); } +#if 0 BOOST_AUTO_TEST_CASE(buffer_8_a_8_const_access) { uint32_t const sz = 8, align = 8; buffer::const_ptr b = create_buffer(); - // (*b)[0] = 0; // Compile time error accessing read-only location + (*b)[0] = 0; // Compile time error accessing read-only location } +#endif // 8 byte buffer size, varying alignment from 1 - 7 BOOST_AUTO_TEST_CASE(buffer_128_a_1_fails) @@ -105,6 +99,7 @@ BOOST_AUTO_TEST_CASE(buffer_128_a_1_fails) buffer::ptr b = create_buffer(); BOOST_CHECK(!b); + BOOST_CHECK_EQUAL((unsigned long) b->raw() & (align - 1), 1); } BOOST_AUTO_TEST_CASE(buffer_128_a_2_succeeds) From 1b49f95c0cdac3d547135de448ec2c0315c0a43a Mon Sep 17 00:00:00 2001 From: Heinz Mauelshagen Date: Wed, 23 Jan 2013 15:08:05 +0100 Subject: [PATCH 3/3] Introduce COMPILE_TIME_ERROR conditionals around tests failing at compile time --- persistent-data/buffer.h | 2 +- unit-tests/buffer_t.cc | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/persistent-data/buffer.h b/persistent-data/buffer.h index 051db59..8ddda70 100644 --- a/persistent-data/buffer.h +++ b/persistent-data/buffer.h @@ -93,7 +93,7 @@ namespace persistent_data { static void check_index(unsigned index) { if (index >= Size) - throw std::runtime_error("buffer index out of bounds"); + throw std::range_error("buffer index out of bounds"); } }; } diff --git a/unit-tests/buffer_t.cc b/unit-tests/buffer_t.cc index 382b4da..88e6a0a 100644 --- a/unit-tests/buffer_t.cc +++ b/unit-tests/buffer_t.cc @@ -16,6 +16,9 @@ // with thin-provisioning-tools. If not, see // . +// Set to one to add compile time checks. +#define COMPILE_TIME_ERROR 0 + #include "persistent-data/buffer.h" #define BOOST_TEST_MODULE BufferTests @@ -49,14 +52,16 @@ namespace { //---------------------------------------------------------------- +#if COMPILE_TIME_ERROR BOOST_AUTO_TEST_CASE(buffer_copy_fails) { uint32_t const sz = 8, align = 8; buffer::ptr b1 = create_buffer(); buffer::ptr b2; - // *b2 = *b1; // Compile time failure + *b2 = *b1; // Compile time failure } +#endif BOOST_AUTO_TEST_CASE(buffer_8_a_8_raw_access) { @@ -69,10 +74,19 @@ BOOST_AUTO_TEST_CASE(buffer_8_a_8_raw_access) BOOST_CHECK(p[0] == 0); p[0] = 4; BOOST_CHECK(p[0] == 4); - - // pc[0] = 5; // Compile time error accessing read-only location } +#if COMPILE_TIME_ERROR +BOOST_AUTO_TEST_CASE(buffer_8_a_8_raw_const_access) +{ + uint32_t const sz = 8, align = 8; + buffer::ptr b = create_buffer(); + unsigned char const *pc = b->raw(); + + pc[0] = 5; // Compile time error accessing read-only location +} +#endif + BOOST_AUTO_TEST_CASE(buffer_8_a_8_access) { uint32_t const sz = 8, align = 8; @@ -82,7 +96,7 @@ BOOST_AUTO_TEST_CASE(buffer_8_a_8_access) BOOST_CHECK_EQUAL((*b)[0], 0); } -#if 0 +#if COMPILE_TIME_ERROR BOOST_AUTO_TEST_CASE(buffer_8_a_8_const_access) { uint32_t const sz = 8, align = 8; @@ -92,15 +106,24 @@ BOOST_AUTO_TEST_CASE(buffer_8_a_8_const_access) } #endif +BOOST_AUTO_TEST_CASE(buffer_8_a_8_oob) +{ + uint32_t const sz = 8, align = 8; + buffer::ptr b = create_buffer(); + + BOOST_CHECK_THROW((*b)[8], std::range_error); +} + // 8 byte buffer size, varying alignment from 1 - 7 +#if COMPILE_TIME_ERROR BOOST_AUTO_TEST_CASE(buffer_128_a_1_fails) { uint32_t const sz = 128, align = 1; buffer::ptr b = create_buffer(); BOOST_CHECK(!b); - BOOST_CHECK_EQUAL((unsigned long) b->raw() & (align - 1), 1); } +#endif BOOST_AUTO_TEST_CASE(buffer_128_a_2_succeeds) { @@ -110,6 +133,7 @@ BOOST_AUTO_TEST_CASE(buffer_128_a_2_succeeds) BOOST_CHECK(b); } +#if COMPILE_TIME_ERROR BOOST_AUTO_TEST_CASE(buffer_128_a_3_fails) { uint32_t const sz = 128, align = 3; @@ -117,6 +141,7 @@ BOOST_AUTO_TEST_CASE(buffer_128_a_3_fails) BOOST_CHECK(!b); } +#endif BOOST_AUTO_TEST_CASE(buffer_128_a_4_succeeds) { @@ -126,6 +151,7 @@ BOOST_AUTO_TEST_CASE(buffer_128_a_4_succeeds) BOOST_CHECK(b); } +#if COMPILE_TIME_ERROR BOOST_AUTO_TEST_CASE(buffer_128_a_5_fails) { uint32_t const sz = 128, align = 5; @@ -149,6 +175,7 @@ BOOST_AUTO_TEST_CASE(buffer_128_a_7_fails) BOOST_CHECK(!b); } +#endif // Varying buffer size, alignment 8 BOOST_AUTO_TEST_CASE(buffer_8_a_8) @@ -329,5 +356,6 @@ BOOST_AUTO_TEST_CASE(buffer_8192_a_16) BOOST_CHECK_EQUAL((unsigned long) b->raw() & (align - 1), 0); } +#undef COMPILE_TIME_ERROR //----------------------------------------------------------------