Improve test coverage a little

This commit is contained in:
Daniel James
2017-04-28 21:06:03 +01:00
parent 5f6ee3da9c
commit cae6b121b2
5 changed files with 298 additions and 36 deletions

View File

@ -62,6 +62,7 @@ test-suite unordered
[ run unordered/rehash_tests.cpp ]
[ run unordered/equality_tests.cpp ]
[ run unordered/swap_tests.cpp ]
[ run unordered/detail_tests.cpp ]
[ run unordered/compile_set.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE

View File

@ -19,6 +19,21 @@ UNORDERED_AUTO_TEST(at_tests)
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
boost::unordered_map<std::string, int> x;
boost::unordered_map<std::string, int> const& x_const(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl;
try {
x.at("one");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) {
}
try {
x_const.at("one");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) {
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
@ -29,6 +44,8 @@ UNORDERED_AUTO_TEST(at_tests)
BOOST_TEST(x.at("one") == 1);
BOOST_TEST(x.at("two") == 2);
BOOST_TEST(x_const.at("one") == 1);
BOOST_TEST(x_const.at("two") == 2);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check missing element" << std::endl;
@ -38,6 +55,12 @@ UNORDERED_AUTO_TEST(at_tests)
} catch (std::out_of_range) {
}
try {
x_const.at("three");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) {
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
}
}

View File

@ -339,10 +339,16 @@ void unordered_map_test(X& r, Key const& k, T const& v)
// Calling functions
r.insert(std::pair<Key const, T>(k, v));
r.insert(r.begin(), std::pair<Key const, T>(k, v));
std::pair<Key const, T> const value(k, v);
r.insert(value);
r.insert(r.end(), value);
Key k_lvalue(k);
T v_lvalue(v);
// Emplace
r.emplace(k, v);
r.emplace(k_lvalue, v_lvalue);
r.emplace(rvalue(k), rvalue(v));
@ -350,6 +356,17 @@ void unordered_map_test(X& r, Key const& k, T const& v)
r.emplace(boost::unordered::piecewise_construct, boost::make_tuple(k),
boost::make_tuple(v));
// Emplace with hint
r.emplace_hint(r.begin(), k, v);
r.emplace_hint(r.begin(), k_lvalue, v_lvalue);
r.emplace_hint(r.begin(), rvalue(k), rvalue(v));
r.emplace_hint(r.begin(), boost::unordered::piecewise_construct,
boost::make_tuple(k), boost::make_tuple(v));
// Extract
test::check_return_type<node_type>::equals(r.extract(r.begin()));
r.emplace(k, v);
@ -360,7 +377,11 @@ void unordered_map_test(X& r, Key const& k, T const& v)
test::check_return_type<key_type>::equals_ref(n1.key());
test::check_return_type<T>::equals_ref(n1.mapped());
r.insert(boost::move(n1));
node_type n2 = boost::move(n1);
r.insert(boost::move(n2));
r.insert(r.extract(r.begin()));
n2 = r.extract(r.begin());
r.insert(r.begin(), boost::move(n2));
r.insert(r.end(), r.extract(r.begin()));
node_type n = r.extract(r.begin());
@ -666,6 +687,13 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
sink(X(b, m));
X a9a(b, m);
X b1;
b1.insert(t);
X a9b(b1);
sink(a9b);
X a9c(b1, m);
sink(a9c);
const_iterator q = a.cbegin();
test::check_return_type<iterator>::equals(a.insert(q, t));

View File

@ -0,0 +1,104 @@
// Copyright 2017 Daniel James.
// 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 <iostream>
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include <map>
// Pretty inefficient, but the test is fast enough.
// Might be too slow if we had larger primes?
bool is_prime(std::size_t x)
{
if (x == 2) {
return true;
} else if (x == 1 || x % 2 == 0) {
return false;
} else {
// y*y <= x had rounding errors, so instead use y <= (x/y).
for (std::size_t y = 3; y <= (x / y); y += 2) {
if (x % y == 0) {
return false;
break;
}
}
return true;
}
}
void test_next_prime(std::size_t value)
{
std::size_t x = boost::unordered::detail::next_prime(value);
BOOST_TEST(is_prime(x));
BOOST_TEST(x >= value);
}
void test_prev_prime(std::size_t value)
{
std::size_t x = boost::unordered::detail::prev_prime(value);
BOOST_TEST(is_prime(x));
BOOST_TEST(x <= value);
if (x > value) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << x << "," << value << std::endl;
}
}
UNORDERED_AUTO_TEST(next_prime_test)
{
BOOST_TEST(!is_prime(0));
BOOST_TEST(!is_prime(1));
BOOST_TEST(is_prime(2));
BOOST_TEST(is_prime(3));
BOOST_TEST(is_prime(13));
BOOST_TEST(!is_prime(4));
BOOST_TEST(!is_prime(100));
BOOST_TEST(boost::unordered::detail::next_prime(0) > 0);
// test_prev_prime doesn't work for values less than 17.
// Which should be okay, unless an allocator has a really tiny
// max_size?
const std::size_t min_prime = 17;
// test_next_prime doesn't work for values greater than this,
// which might be a problem if you've got terrabytes of memory?
// I seriously doubt the container would work well at such sizes
// regardless.
const std::size_t max_prime = 4294967291ul;
std::size_t i;
BOOST_TEST(is_prime(min_prime));
BOOST_TEST(is_prime(max_prime));
for (i = 0; i < 10000; ++i) {
if (i < min_prime) {
BOOST_TEST(boost::unordered::detail::prev_prime(i) == min_prime);
} else {
test_prev_prime(i);
}
test_next_prime(i);
}
std::size_t last = i - 1;
for (; i > last; last = i, i += i / 5) {
if (i > max_prime) {
BOOST_TEST(boost::unordered::detail::next_prime(i) == max_prime);
} else {
test_next_prime(i);
}
test_prev_prime(i);
}
}
RUN_TESTS()

View File

@ -35,64 +35,138 @@ void unique_insert_tests1(X*, test::random_generator generator)
std::cerr << "insert(value) tests for containers with unique keys.\n";
X x;
test::ordered<X> tracker = test::create_ordered(x);
{
X x;
test::ordered<X> tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
test::random_values<X> v(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it) {
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
v.begin();
it != v.end(); ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
float b = x.max_load_factor();
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
x.bucket_count();
float b = x.max_load_factor();
std::pair<iterator, bool> r1 = x.insert(*it);
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool> r2 =
tracker.insert(*it);
std::pair<iterator, bool> r1 = x.insert(*it);
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool> r2 =
tracker.insert(*it);
BOOST_TEST(r1.second == r2.second);
BOOST_TEST(*r1.first == *r2.first);
BOOST_TEST(r1.second == r2.second);
BOOST_TEST(*r1.first == *r2.first);
tracker.compare_key(x, *it);
tracker.compare_key(x, *it);
if (static_cast<double>(x.size()) <=
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
if (static_cast<double>(x.size()) <=
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
test::check_equivalent_keys(x);
std::cerr << "insert(rvalue) tests for containers with unique keys.\n";
{
X x;
test::ordered<X> tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
v.begin();
it != v.end(); ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
x.bucket_count();
float b = x.max_load_factor();
typename X::value_type value = *it;
std::pair<iterator, bool> r1 = x.insert(boost::move(value));
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool> r2 =
tracker.insert(*it);
BOOST_TEST(r1.second == r2.second);
BOOST_TEST(*r1.first == *r2.first);
tracker.compare_key(x, *it);
if (static_cast<double>(x.size()) <=
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
}
template <class X>
void equivalent_insert_tests1(X*, test::random_generator generator)
{
std::cerr << "insert(value) tests for containers with equivalent keys.\n";
test::check_instances check_;
X x;
test::ordered<X> tracker = test::create_ordered(x);
std::cerr << "insert(value) tests for containers with equivalent keys.\n";
test::random_values<X> v(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
float b = x.max_load_factor();
{
X x;
test::ordered<X> tracker = test::create_ordered(x);
BOOST_DEDUCED_TYPENAME X::iterator r1 = x.insert(*it);
BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator r2 =
tracker.insert(*it);
test::random_values<X> v(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
v.begin();
it != v.end(); ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
x.bucket_count();
float b = x.max_load_factor();
BOOST_TEST(*r1 == *r2);
BOOST_DEDUCED_TYPENAME X::iterator r1 = x.insert(*it);
BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator r2 =
tracker.insert(*it);
tracker.compare_key(x, *it);
BOOST_TEST(*r1 == *r2);
if (static_cast<double>(x.size()) <=
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
tracker.compare_key(x, *it);
if (static_cast<double>(x.size()) <=
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
test::check_equivalent_keys(x);
std::cerr << "insert(rvalue) tests for containers with equivalent keys.\n";
{
X x;
test::ordered<X> tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
v.begin();
it != v.end(); ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
x.bucket_count();
float b = x.max_load_factor();
typename X::value_type value = *it;
BOOST_DEDUCED_TYPENAME X::iterator r1 =
x.insert(boost::move(value));
BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator r2 =
tracker.insert(*it);
BOOST_TEST(*r1 == *r2);
tracker.compare_key(x, *it);
if (static_cast<double>(x.size()) <=
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
}
template <class X> void insert_tests2(X*, test::random_generator generator)
@ -194,6 +268,38 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
test::check_equivalent_keys(x);
}
std::cerr << "insert(pos, rvalue) tests.\n";
{
test::check_instances check_;
X x;
const_iterator pos = x.begin();
tracker_type tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
v.begin();
it != v.end(); ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
x.bucket_count();
float b = x.max_load_factor();
typename X::value_type value = *it;
pos = x.insert(pos, boost::move(value));
tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
BOOST_TEST(*pos == *r2);
tracker.compare_key(x, *it);
if (static_cast<double>(x.size()) <=
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
tracker.compare(x);
test::check_equivalent_keys(x);
}
std::cerr << "insert single item range tests.\n";
{