253 lines
6.3 KiB
C++
253 lines
6.3 KiB
C++
/*
|
|
* Unit tests for PriorityQueue data structure.
|
|
*
|
|
* Depends on the Boost.Test unit test framework.
|
|
* Tested with Boost v1.74, available from https://www.boost.org/
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <climits>
|
|
#include <memory>
|
|
#include <random>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <vector>
|
|
|
|
#define BOOST_TEST_MODULE priority_queue
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
#include "priority_queue.hpp"
|
|
|
|
|
|
BOOST_AUTO_TEST_SUITE(test_priority_queue)
|
|
|
|
BOOST_AUTO_TEST_CASE(test_empty)
|
|
{
|
|
using Queue = mwmatching::PriorityQueue<int, std::string>;
|
|
Queue q;
|
|
BOOST_TEST(q.empty() == true);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_single)
|
|
{
|
|
using Queue = mwmatching::PriorityQueue<int, std::string>;
|
|
Queue q;
|
|
|
|
Queue::Node n1;
|
|
BOOST_TEST(n1.valid() == false);
|
|
|
|
q.insert(&n1, 5, "a");
|
|
|
|
BOOST_TEST(n1.valid() == true);
|
|
BOOST_TEST(n1.prio() == 5);
|
|
BOOST_TEST(q.empty() == false);
|
|
BOOST_TEST(q.min_prio() == 5);
|
|
BOOST_TEST(q.min_elem() == std::string("a"));
|
|
|
|
q.set_prio(&n1, 3);
|
|
BOOST_TEST(n1.prio() == 3);
|
|
BOOST_TEST(q.min_prio() == 3);
|
|
BOOST_TEST(q.min_elem() == std::string("a"));
|
|
|
|
q.remove(&n1);
|
|
BOOST_TEST(n1.valid() == false);
|
|
BOOST_TEST(q.empty() == true);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_simple)
|
|
{
|
|
using Queue = mwmatching::PriorityQueue<int, char>;
|
|
Queue q;
|
|
Queue::Node nodes[10];
|
|
|
|
q.insert(&nodes[0], 9, 'a');
|
|
BOOST_TEST(q.min_prio() == 9);
|
|
BOOST_TEST(q.min_elem() == 'a');
|
|
|
|
q.insert(&nodes[1], 4, 'b');
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
BOOST_TEST(q.min_elem() == 'b');
|
|
|
|
q.insert(&nodes[2], 7, 'c');
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
BOOST_TEST(q.min_elem() == 'b');
|
|
|
|
q.insert(&nodes[3], 5, 'd');
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
BOOST_TEST(q.min_elem() == 'b');
|
|
|
|
q.insert(&nodes[4], 8, 'e');
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
BOOST_TEST(q.min_elem() == 'b');
|
|
|
|
q.insert(&nodes[5], 6, 'f');
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
BOOST_TEST(q.min_elem() == 'b');
|
|
|
|
q.insert(&nodes[6], 4, 'g');
|
|
q.insert(&nodes[7], 5, 'h');
|
|
q.insert(&nodes[8], 2, 'i');
|
|
BOOST_TEST(q.min_prio() == 2);
|
|
BOOST_TEST(q.min_elem() == 'i');
|
|
|
|
q.insert(&nodes[9], 6, 'j');
|
|
BOOST_TEST(q.min_prio() == 2);
|
|
BOOST_TEST(q.min_elem() == 'i');
|
|
|
|
q.set_prio(&nodes[2], 1);
|
|
BOOST_TEST(q.min_prio() == 1);
|
|
BOOST_TEST(q.min_elem() == 'c');
|
|
|
|
q.set_prio(&nodes[4], 3);
|
|
BOOST_TEST(q.min_prio() == 1);
|
|
BOOST_TEST(q.min_elem() == 'c');
|
|
|
|
q.remove(&nodes[2]);
|
|
BOOST_TEST(q.min_prio() == 2);
|
|
BOOST_TEST(q.min_elem() == 'i');
|
|
|
|
q.remove(&nodes[8]);
|
|
BOOST_TEST(q.min_prio() == 3);
|
|
BOOST_TEST(q.min_elem() == 'e');
|
|
|
|
q.remove(&nodes[4]);
|
|
q.remove(&nodes[1]);
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
BOOST_TEST(q.min_elem() == 'g');
|
|
|
|
q.remove(&nodes[3]);
|
|
q.remove(&nodes[9]);
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
BOOST_TEST(q.min_elem() == 'g');
|
|
|
|
q.remove(&nodes[6]);
|
|
BOOST_TEST(q.min_prio() == 5);
|
|
BOOST_TEST(q.min_elem() == 'h');
|
|
|
|
BOOST_TEST(q.empty() == false);
|
|
q.clear();
|
|
BOOST_TEST(q.empty() == true);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_increase_prio)
|
|
{
|
|
using Queue = mwmatching::PriorityQueue<int, char>;
|
|
|
|
Queue q;
|
|
Queue::Node n1;
|
|
|
|
q.insert(&n1, 5, 'a');
|
|
q.set_prio(&n1, 8);
|
|
BOOST_TEST(n1.prio() == 8);
|
|
BOOST_TEST(q.min_prio() == 8);
|
|
|
|
q.clear();
|
|
|
|
Queue::Node n2, n3, n4;
|
|
|
|
q.insert(&n1, 9, 'A');
|
|
q.insert(&n2, 4, 'b');
|
|
q.insert(&n3, 7, 'c');
|
|
q.insert(&n4, 5, 'd');
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
BOOST_TEST(q.min_elem() == 'b');
|
|
|
|
q.set_prio(&n2, 8);
|
|
BOOST_TEST(n2.prio() == 8);
|
|
BOOST_TEST(q.min_elem() == 'd');
|
|
BOOST_TEST(q.min_prio() == 5);
|
|
|
|
q.set_prio(&n3, 10);
|
|
BOOST_TEST(n3.prio() == 10);
|
|
BOOST_TEST(q.min_elem() == 'd');
|
|
|
|
q.remove(&n4);
|
|
BOOST_TEST(q.min_elem() == 'b');
|
|
|
|
q.remove(&n2);
|
|
BOOST_TEST(q.min_prio() == 9);
|
|
BOOST_TEST(q.min_elem() == 'A');
|
|
|
|
q.remove(&n1);
|
|
BOOST_TEST(q.min_elem() == 'c');
|
|
BOOST_TEST(q.min_prio() == 10);
|
|
|
|
q.remove(&n3);
|
|
BOOST_TEST(q.empty() == true);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_random)
|
|
{
|
|
using Queue = mwmatching::PriorityQueue<int, int>;
|
|
Queue q;
|
|
|
|
const int num_elem = 1000;
|
|
std::vector<std::tuple<std::unique_ptr<Queue::Node>, int, int>> elems;
|
|
int next_data = 0;
|
|
|
|
std::mt19937 rng(34567);
|
|
|
|
auto check = [&q,&elems]() {
|
|
int min_prio = q.min_prio();
|
|
int min_data = q.min_elem();
|
|
int best_prio = INT_MAX;
|
|
bool found = false;
|
|
for (const auto& v : elems) {
|
|
int this_prio = std::get<1>(v);
|
|
int this_data = std::get<2>(v);
|
|
best_prio = std::min(best_prio, this_prio);
|
|
if ((this_prio == min_prio) && (this_data == min_data)) {
|
|
found = true;
|
|
}
|
|
}
|
|
BOOST_TEST(found == true);
|
|
BOOST_TEST(min_prio == best_prio);
|
|
};
|
|
|
|
for (int i = 0; i < num_elem; ++i) {
|
|
++next_data;
|
|
int prio = std::uniform_int_distribution<>(0, 1000000)(rng);
|
|
std::unique_ptr<Queue::Node> nptr(new Queue::Node);
|
|
q.insert(nptr.get(), prio, next_data);
|
|
elems.push_back(std::make_tuple(std::move(nptr), prio, next_data));
|
|
check();
|
|
}
|
|
|
|
for (int i = 0; i < 10000; ++i) {
|
|
int p = std::uniform_int_distribution<>(0, num_elem - 1)(rng);
|
|
Queue::Node* node = std::get<0>(elems[p]).get();
|
|
int prio = std::get<1>(elems[p]);
|
|
prio = std::uniform_int_distribution<>(0, 1000000)(rng);
|
|
q.set_prio(node, prio);
|
|
std::get<1>(elems[p]) = prio;
|
|
check();
|
|
|
|
p = std::uniform_int_distribution<>(0, num_elem - 1)(rng);
|
|
node = std::get<0>(elems[p]).get();
|
|
q.remove(node);
|
|
elems.erase(elems.begin() + p);
|
|
check();
|
|
|
|
++next_data;
|
|
prio = std::uniform_int_distribution<>(0, 1000000)(rng);
|
|
std::unique_ptr<Queue::Node> nptr(new Queue::Node);
|
|
q.insert(nptr.get(), prio, next_data);
|
|
elems.push_back(std::make_tuple(std::move(nptr), prio, next_data));
|
|
check();
|
|
}
|
|
|
|
for (int i = 0; i < num_elem; ++i) {
|
|
int p = std::uniform_int_distribution<>(0, num_elem - 1 - i)(rng);
|
|
Queue::Node* node = std::get<0>(elems[p]).get();
|
|
q.remove(node);
|
|
elems.erase(elems.begin() + p);
|
|
if (! elems.empty()) {
|
|
check();
|
|
}
|
|
}
|
|
|
|
BOOST_TEST(q.empty() == true);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|