| // ----------------------------------------------------------- |
| // Copyright (c) 2001 Jeremy Siek |
| // Copyright (c) 2003-2006 Gennaro Prota |
| // |
| // Distributed under the Boost Software License, Version 1.0. |
| // (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| // |
| // ----------------------------------------------------------- |
| |
| #include "bitset_test.hpp" |
| #include "boost/dynamic_bitset/dynamic_bitset.hpp" |
| #include "boost/limits.hpp" |
| #include "boost/config.hpp" |
| |
| #include "boost/detail/workaround.hpp" |
| |
| #define BOOST_BITSET_TEST_COUNT(x) (sizeof(x)/sizeof(x[0])) |
| |
| |
| // Codewarrior 8.3 for Win fails without this. |
| // Thanks Howard Hinnant ;) |
| #if defined __MWERKS__ && BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x |
| # pragma parse_func_templ off |
| #endif |
| |
| |
| template <typename Tests, typename String> |
| void run_string_tests(const String& s |
| BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tests) |
| ) |
| { |
| |
| const std::size_t len = s.length(); |
| const std::size_t step = len/4 ? len/4 : 1; |
| |
| // bitset length determined by the string-related arguments |
| std::size_t i; |
| for (i = 0; i <= len/2 ; i += step) { |
| Tests::from_string(s, i, len/2); // len/2 - i bits |
| Tests::from_string(s, i, len); // len - i bits |
| Tests::from_string(s, i, 1 + len*2); // len - i bits |
| } |
| |
| // bitset length explicitly specified |
| for (i = 0; i <= len/2; i += step) { |
| for (std::size_t sz = 0; sz <= len*4; sz+= step*2) { |
| Tests::from_string(s, i, len/2, sz); |
| Tests::from_string(s, i, len, sz); |
| Tests::from_string(s, i, 1 + len*2, sz); |
| |
| } |
| } |
| |
| } |
| |
| // tests the do-the-right-thing constructor dispatch |
| template <typename Tests, typename T> |
| void run_numeric_ctor_tests( BOOST_EXPLICIT_TEMPLATE_TYPE(Tests) |
| BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T) ) |
| { |
| |
| const int bits_per_block = Tests::bits_per_block; |
| const int width = std::numeric_limits<T>::digits; |
| const T ma = (std::numeric_limits<T>::max)(); |
| const T mi = (std::numeric_limits<T>::min)(); |
| |
| int sizes[] = { |
| 0, 7*width/10, width, 13*width/10, 3*width, |
| 7*bits_per_block/10, bits_per_block, 13*bits_per_block/10, 3*bits_per_block |
| }; |
| |
| const T numbers[] = { |
| T(-1), T(-3), T(-8), T(-15), mi/2, mi, |
| 0, 1, 3, 8, 15, ma/2, ma |
| }; |
| |
| for (std::size_t s = 0; s < BOOST_BITSET_TEST_COUNT(sizes); ++s) { |
| for (std::size_t n = 0; n < BOOST_BITSET_TEST_COUNT(numbers); ++n ) { |
| |
| // can match ctor from ulong or templated one |
| Tests::from_unsigned_long(sizes[s], numbers[n]); |
| |
| typedef std::size_t compare_type; |
| const compare_type sz = sizes[s]; |
| // this condition is to be sure that size is representable in T, so |
| // that for signed T's we avoid implementation-defined behavior [if ma |
| // is larger than what std::size_t can hold then this is ok for our |
| // purposes: our sizes are anyhow < max(size_t)], which in turn could |
| // make the first argument of from_unsigned_long() a small negative, |
| // later converted to a very large unsigned. Example: signed 8-bit |
| // char (CHAR_MAX=127), bits_per_block=64, sz = 192 > 127. |
| const bool fits = |
| sz <= static_cast<compare_type>(ma); |
| |
| if (fits) { |
| // can match templated ctor only (so we test dispatching) |
| Tests::from_unsigned_long(static_cast<T>(sizes[s]), numbers[n]); |
| } |
| |
| } |
| } |
| |
| } |
| |
| |
| template <typename Block> |
| void run_test_cases( BOOST_EXPLICIT_TEMPLATE_TYPE(Block) ) |
| { |
| typedef boost::dynamic_bitset<Block> bitset_type; |
| typedef bitset_test<bitset_type> Tests; |
| const int bits_per_block = bitset_type::bits_per_block; |
| |
| const std::string long_string = get_long_string(); |
| const Block all_1s = static_cast<Block>(-1); |
| |
| //===================================================================== |
| // Test construction from unsigned long |
| { |
| typedef typename bitset_type::size_type size_type; |
| |
| |
| // NOTE: |
| // |
| // 1. keep this in sync with the numeric types supported |
| // for constructor dispatch (of course) |
| // 2. bool is tested separately; ugly and inelegant, but |
| // we don't have much time to think of a better solution |
| // which is likely to work on broken compilers |
| // |
| const int sizes[] = { |
| 0, 1, 3, |
| 7*bits_per_block/10, bits_per_block, 13*bits_per_block/10, 3*bits_per_block |
| }; |
| |
| const bool values[] = { false, true }; |
| |
| for (std::size_t s = 0; s < BOOST_BITSET_TEST_COUNT(sizes); ++s) { |
| for (std::size_t v = 0; v < BOOST_BITSET_TEST_COUNT(values); ++v) { |
| Tests::from_unsigned_long(sizes[s], values[v]); |
| Tests::from_unsigned_long(sizes[s] != 0, values[v]); |
| } |
| } |
| |
| run_numeric_ctor_tests<Tests, char>(); |
| |
| #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) |
| run_numeric_ctor_tests<Tests, wchar_t>(); |
| #endif |
| |
| run_numeric_ctor_tests<Tests, signed char>(); |
| run_numeric_ctor_tests<Tests, short int>(); |
| run_numeric_ctor_tests<Tests, int>(); |
| run_numeric_ctor_tests<Tests, long int>(); |
| |
| run_numeric_ctor_tests<Tests, unsigned char>(); |
| run_numeric_ctor_tests<Tests, unsigned short>(); |
| run_numeric_ctor_tests<Tests, unsigned int>(); |
| run_numeric_ctor_tests<Tests, unsigned long>(); |
| |
| #if defined(BOOST_HAS_LONG_LONG) |
| run_numeric_ctor_tests<Tests, ::boost::long_long_type>(); |
| run_numeric_ctor_tests<Tests, ::boost::ulong_long_type>(); |
| #endif |
| |
| } |
| //===================================================================== |
| // Test construction from a string |
| { |
| |
| run_string_tests<Tests>(std::string("")); // empty string |
| run_string_tests<Tests>(std::string("1")); |
| |
| run_string_tests<Tests>(long_string); |
| |
| # if !defined BOOST_NO_STD_WSTRING |
| // I need to decide what to do for non "C" locales here. On |
| // one hand I should have better tests. On the other one |
| // I don't want tests for dynamic_bitset to cope with locales, |
| // ctype::widen, etc. (but that's what you deserve when you |
| // don't separate concerns at the library level) |
| // |
| run_string_tests<Tests>( |
| std::wstring(L"11111000000111111111010101010101010101010111111")); |
| # endif |
| |
| // Note that these are _valid_ arguments |
| Tests::from_string(std::string("x11y"), 1, 2); |
| Tests::from_string(std::string("x11"), 1, 10); |
| Tests::from_string(std::string("x11"), 1, 10, 10); |
| |
| } |
| //===================================================================== |
| // test from_block_range |
| { |
| std::vector<Block> blocks; |
| Tests::from_block_range(blocks); |
| } |
| { |
| std::vector<Block> blocks(3); |
| blocks[0] = static_cast<Block>(0); |
| blocks[1] = static_cast<Block>(1); |
| blocks[2] = all_1s; |
| Tests::from_block_range(blocks); |
| } |
| { |
| const unsigned int n = (std::numeric_limits<unsigned char>::max)(); |
| std::vector<Block> blocks(n); |
| for (typename std::vector<Block>::size_type i = 0; i < n; ++i) |
| blocks[i] = static_cast<Block>(i); |
| Tests::from_block_range(blocks); |
| } |
| //===================================================================== |
| // test to_block_range |
| { |
| bitset_type b; |
| Tests::to_block_range(b); |
| } |
| { |
| bitset_type b(1, 1ul); |
| Tests::to_block_range(b); |
| } |
| { |
| bitset_type b(long_string); |
| Tests::to_block_range(b); |
| } |
| |
| //===================================================================== |
| // Test copy constructor |
| { |
| boost::dynamic_bitset<Block> b; |
| Tests::copy_constructor(b); |
| } |
| { |
| boost::dynamic_bitset<Block> b(std::string("0")); |
| Tests::copy_constructor(b); |
| } |
| { |
| boost::dynamic_bitset<Block> b(long_string); |
| Tests::copy_constructor(b); |
| } |
| //===================================================================== |
| // Test assignment operator |
| { |
| bitset_type a, b; |
| Tests::assignment_operator(a, b); |
| } |
| { |
| bitset_type a(std::string("1")), b(std::string("0")); |
| Tests::assignment_operator(a, b); |
| } |
| { |
| bitset_type a(long_string), b(long_string); |
| Tests::assignment_operator(a, b); |
| } |
| { |
| bitset_type a; |
| bitset_type b(long_string); // b greater than a, a empty |
| Tests::assignment_operator(a, b); |
| } |
| { |
| bitset_type a(std::string("0")); |
| bitset_type b(long_string); // b greater than a |
| Tests::assignment_operator(a, b); |
| } |
| //===================================================================== |
| // Test swap |
| { |
| bitset_type a; |
| bitset_type b(std::string("1")); |
| Tests::swap(a, b); |
| Tests::swap(b, a); |
| Tests::swap(a, a); |
| } |
| { |
| bitset_type a; |
| bitset_type b(long_string); |
| Tests::swap(a, b); |
| Tests::swap(b, a); |
| } |
| { |
| bitset_type a(std::string("0")); |
| bitset_type b(long_string); |
| Tests::swap(a, b); |
| Tests::swap(b, a); |
| Tests::swap(a, a); |
| Tests::swap(b, b); |
| } |
| //===================================================================== |
| // Test resize |
| { |
| boost::dynamic_bitset<Block> a; |
| Tests::resize(a); |
| } |
| { |
| boost::dynamic_bitset<Block> a(std::string("0")); |
| Tests::resize(a); |
| } |
| { |
| boost::dynamic_bitset<Block> a(std::string("1")); |
| Tests::resize(a); |
| } |
| { |
| boost::dynamic_bitset<Block> a(long_string); |
| Tests::resize(a); |
| } |
| //===================================================================== |
| // Test clear |
| { |
| boost::dynamic_bitset<Block> a; |
| Tests::clear(a); |
| } |
| { |
| boost::dynamic_bitset<Block> a(long_string); |
| Tests::clear(a); |
| } |
| //===================================================================== |
| // Test append bit |
| { |
| boost::dynamic_bitset<Block> a; |
| Tests::append_bit(a); |
| } |
| { |
| boost::dynamic_bitset<Block> a(std::string("0")); |
| Tests::append_bit(a); |
| } |
| { |
| boost::dynamic_bitset<Block> a(std::string("1")); |
| Tests::append_bit(a); |
| } |
| { |
| const int size_to_fill_all_blocks = 4 * bits_per_block; |
| boost::dynamic_bitset<Block> a(size_to_fill_all_blocks, 255ul); |
| Tests::append_bit(a); |
| } |
| { |
| boost::dynamic_bitset<Block> a(long_string); |
| Tests::append_bit(a); |
| } |
| //===================================================================== |
| // Test append block |
| { |
| boost::dynamic_bitset<Block> a; |
| Tests::append_block(a); |
| } |
| { |
| boost::dynamic_bitset<Block> a(std::string("0")); |
| Tests::append_block(a); |
| } |
| { |
| boost::dynamic_bitset<Block> a(std::string("1")); |
| Tests::append_block(a); |
| } |
| { |
| const int size_to_fill_all_blocks = 4 * bits_per_block; |
| boost::dynamic_bitset<Block> a(size_to_fill_all_blocks, 15ul); |
| Tests::append_block(a); |
| } |
| { |
| boost::dynamic_bitset<Block> a(long_string); |
| Tests::append_block(a); |
| } |
| //===================================================================== |
| // Test append block range |
| { |
| boost::dynamic_bitset<Block> a; |
| std::vector<Block> blocks; |
| Tests::append_block_range(a, blocks); |
| } |
| { |
| boost::dynamic_bitset<Block> a(std::string("0")); |
| std::vector<Block> blocks(3); |
| blocks[0] = static_cast<Block>(0); |
| blocks[1] = static_cast<Block>(1); |
| blocks[2] = all_1s; |
| Tests::append_block_range(a, blocks); |
| } |
| { |
| boost::dynamic_bitset<Block> a(std::string("1")); |
| const unsigned int n = (std::numeric_limits<unsigned char>::max)(); |
| std::vector<Block> blocks(n); |
| for (typename std::vector<Block>::size_type i = 0; i < n; ++i) |
| blocks[i] = static_cast<Block>(i); |
| Tests::append_block_range(a, blocks); |
| } |
| { |
| boost::dynamic_bitset<Block> a; |
| a.append(Block(1)); |
| a.append(Block(2)); |
| Block x[] = {3, 4, 5}; |
| std::size_t sz = sizeof(x) / sizeof(x[0]); |
| std::vector<Block> blocks(x, x + sz); |
| Tests::append_block_range(a, blocks); |
| } |
| { |
| boost::dynamic_bitset<Block> a(long_string); |
| std::vector<Block> blocks(3); |
| blocks[0] = static_cast<Block>(0); |
| blocks[1] = static_cast<Block>(1); |
| blocks[2] = all_1s; |
| Tests::append_block_range(a, blocks); |
| } |
| //===================================================================== |
| // Test bracket operator |
| { |
| boost::dynamic_bitset<Block> b1; |
| std::vector<bool> bitvec1; |
| Tests::operator_bracket(b1, bitvec1); |
| } |
| { |
| boost::dynamic_bitset<Block> b(std::string("1")); |
| std::vector<bool> bit_vec(1, true); |
| Tests::operator_bracket(b, bit_vec); |
| } |
| { |
| boost::dynamic_bitset<Block> b(long_string); |
| std::size_t n = long_string.size(); |
| std::vector<bool> bit_vec(n); |
| for (std::size_t i = 0; i < n; ++i) |
| bit_vec[i] = long_string[n - 1 - i] == '0' ? 0 : 1; |
| Tests::operator_bracket(b, bit_vec); |
| } |
| } |
| |
| int |
| test_main(int, char*[]) |
| { |
| run_test_cases<unsigned char>(); |
| run_test_cases<unsigned short>(); |
| run_test_cases<unsigned int>(); |
| run_test_cases<unsigned long>(); |
| # ifdef BOOST_HAS_LONG_LONG |
| run_test_cases< ::boost::ulong_long_type>(); |
| # endif |
| |
| return 0; |
| } |