#include "util/sorted_uniform.hh" #include #include #include #include #include #define BOOST_TEST_MODULE SortedUniformTest #include #include #include #include namespace util { namespace { template struct Entry { typedef KeyT Key; typedef ValueT Value; Key key; Value value; Key GetKey() const { return key; } Value GetValue() const { return value; } bool operator<(const Entry &other) const { return key < other.key; } }; template struct Accessor { typedef KeyT Key; template Key operator()(const Entry *entry) const { return entry->GetKey(); } }; template void Check(const Entry *begin, const Entry *end, const boost::unordered_map &reference, const Key key) { typename boost::unordered_map::const_iterator ref = reference.find(key); typedef const Entry *It; // g++ can't tell that require will crash and burn. It i = NULL; bool ret = SortedUniformFind, Pivot64>(Accessor(), begin, end, key, i); if (ref == reference.end()) { BOOST_CHECK(!ret); } else { BOOST_REQUIRE(ret); BOOST_CHECK_EQUAL(ref->second, i->GetValue()); } } BOOST_AUTO_TEST_CASE(empty) { typedef const Entry T; const T *i; bool ret = SortedUniformFind, Pivot64>(Accessor(), (const T*)NULL, (const T*)NULL, (uint64_t)10, i); BOOST_CHECK(!ret); } template void RandomTest(Key upper, size_t entries, size_t queries) { typedef unsigned char Value; boost::mt19937 rng; boost::uniform_int range_key(0, upper); boost::uniform_int range_value(0, 255); boost::variate_generator > gen_key(rng, range_key); boost::variate_generator > gen_value(rng, range_value); typedef Entry Ent; std::vector backing; boost::unordered_map reference; Ent ent; for (size_t i = 0; i < entries; ++i) { Key key = gen_key(); unsigned char value = gen_value(); if (reference.insert(std::make_pair(key, value)).second) { ent.key = key; ent.value = value; backing.push_back(ent); } } std::sort(backing.begin(), backing.end()); // Random queries. for (size_t i = 0; i < queries; ++i) { const Key key = gen_key(); Check(&*backing.begin(), &*backing.end(), reference, key); } typename boost::unordered_map::const_iterator it = reference.begin(); for (size_t i = 0; (i < queries) && (it != reference.end()); ++i, ++it) { Check(&*backing.begin(), &*backing.end(), reference, it->second); } } BOOST_AUTO_TEST_CASE(basic) { RandomTest(11, 10, 200); } BOOST_AUTO_TEST_CASE(tiny_dense_random) { RandomTest(11, 50, 200); } BOOST_AUTO_TEST_CASE(small_dense_random) { RandomTest(100, 100, 200); } BOOST_AUTO_TEST_CASE(small_sparse_random) { RandomTest(200, 15, 200); } BOOST_AUTO_TEST_CASE(medium_sparse_random) { RandomTest(32000, 1000, 2000); } BOOST_AUTO_TEST_CASE(sparse_random) { RandomTest(std::numeric_limits::max(), 100000, 2000); } } // namespace } // namespace util