2023-06-16 19:55:43 +02:00
|
|
|
/*
|
|
|
|
* Unit tests for data structures.
|
|
|
|
*
|
|
|
|
* 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>
|
2024-11-08 18:38:20 +01:00
|
|
|
#include <set>
|
2023-06-16 19:55:43 +02:00
|
|
|
#include <string>
|
|
|
|
#include <tuple>
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#define BOOST_TEST_MODULE datastruct
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
|
|
|
|
#include "datastruct.h"
|
|
|
|
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
/* ********** Test ConcatenableQueue ********** */
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_AUTO_TEST_SUITE(test_concatenable_queue)
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(test_single)
|
|
|
|
{
|
2024-11-08 18:38:20 +01:00
|
|
|
using Queue = ConcatenableQueue<int, std::string, std::string>;
|
2024-11-16 23:18:09 +01:00
|
|
|
Queue q("Q");
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.name() == std::string("Q"));
|
|
|
|
|
|
|
|
Queue::Node n;
|
|
|
|
q.insert(&n, 4, "a");
|
|
|
|
|
|
|
|
BOOST_TEST(n.find() == std::string("Q"));
|
|
|
|
BOOST_TEST(n.prio() == 4);
|
|
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
|
|
BOOST_TEST(q.min_elem() == std::string("a"));
|
|
|
|
|
|
|
|
n.set_prio(8);
|
|
|
|
|
|
|
|
BOOST_TEST(n.prio() == 8);
|
|
|
|
BOOST_TEST(n.find() == std::string("Q"));
|
|
|
|
BOOST_TEST(q.min_prio() == 8);
|
|
|
|
BOOST_TEST(q.min_elem() == std::string("a"));
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(test_simple)
|
|
|
|
{
|
2024-11-08 18:38:20 +01:00
|
|
|
using Queue = ConcatenableQueue<int, std::string, char>;
|
|
|
|
Queue::Node n1, n2, n3, n4, n5;
|
|
|
|
|
2024-11-16 23:18:09 +01:00
|
|
|
Queue q1("A");
|
2024-11-08 18:38:20 +01:00
|
|
|
q1.insert(&n1, 5, 'a');
|
|
|
|
|
2024-11-16 23:18:09 +01:00
|
|
|
Queue q2("B");
|
2024-11-08 18:38:20 +01:00
|
|
|
q2.insert(&n2, 6, 'b');
|
|
|
|
|
2024-11-16 23:18:09 +01:00
|
|
|
Queue q3("C");
|
2024-11-08 18:38:20 +01:00
|
|
|
q3.insert(&n3, 7, 'c');
|
|
|
|
|
2024-11-16 23:18:09 +01:00
|
|
|
Queue q4("D");
|
2024-11-08 18:38:20 +01:00
|
|
|
q4.insert(&n4, 4, 'd');
|
|
|
|
|
2024-11-16 23:18:09 +01:00
|
|
|
Queue q5("E");
|
2024-11-08 18:38:20 +01:00
|
|
|
q5.insert(&n5, 3, 'e');
|
|
|
|
|
|
|
|
auto m345 = {&q3, &q4, &q5};
|
2024-11-16 23:18:09 +01:00
|
|
|
Queue q345("P");
|
2024-11-08 18:38:20 +01:00
|
|
|
q345.merge(m345.begin(), m345.end());
|
|
|
|
|
|
|
|
BOOST_TEST(n1.find() == std::string("A"));
|
|
|
|
BOOST_TEST(n2.find() == std::string("B"));
|
|
|
|
BOOST_TEST(n3.find() == std::string("P"));
|
|
|
|
BOOST_TEST(n4.find() == std::string("P"));
|
|
|
|
BOOST_TEST(n5.find() == std::string("P"));
|
|
|
|
BOOST_TEST(q345.min_prio() == 3);
|
|
|
|
BOOST_TEST(q345.min_elem() == 'e');
|
|
|
|
|
|
|
|
n5.set_prio(6);
|
|
|
|
BOOST_TEST(q345.min_prio() == 4);
|
|
|
|
BOOST_TEST(q345.min_elem() == 'd');
|
|
|
|
|
|
|
|
auto m12 = {&q1, &q2};
|
2024-11-16 23:18:09 +01:00
|
|
|
Queue q12("Q");
|
2024-11-08 18:38:20 +01:00
|
|
|
q12.merge(m12.begin(), m12.end());
|
|
|
|
|
|
|
|
BOOST_TEST(n1.find() == std::string("Q"));
|
|
|
|
BOOST_TEST(n2.find() == std::string("Q"));
|
|
|
|
BOOST_TEST(q12.min_prio() == 5);
|
|
|
|
BOOST_TEST(q12.min_elem() == 'a');
|
|
|
|
|
|
|
|
auto m12345 = {&q12, &q345};
|
2024-11-16 23:18:09 +01:00
|
|
|
Queue q12345("R");
|
2024-11-08 18:38:20 +01:00
|
|
|
q12345.merge(m12345.begin(), m12345.end());
|
|
|
|
|
|
|
|
BOOST_TEST(n1.find() == std::string("R"));
|
|
|
|
BOOST_TEST(n2.find() == std::string("R"));
|
|
|
|
BOOST_TEST(n3.find() == std::string("R"));
|
|
|
|
BOOST_TEST(n4.find() == std::string("R"));
|
|
|
|
BOOST_TEST(n5.find() == std::string("R"));
|
|
|
|
BOOST_TEST(q12345.min_prio() == 4);
|
|
|
|
BOOST_TEST(q12345.min_elem() == 'd');
|
|
|
|
|
|
|
|
n4.set_prio(8);
|
|
|
|
|
|
|
|
BOOST_TEST(q12345.min_prio() == 5);
|
|
|
|
BOOST_TEST(q12345.min_elem() == 'a');
|
|
|
|
|
|
|
|
n3.set_prio(2);
|
|
|
|
|
|
|
|
BOOST_TEST(q12345.min_prio() == 2);
|
|
|
|
BOOST_TEST(q12345.min_elem() == 'c');
|
|
|
|
|
|
|
|
q12345.split();
|
|
|
|
|
|
|
|
BOOST_TEST(n1.find() == std::string("Q"));
|
|
|
|
BOOST_TEST(n2.find() == std::string("Q"));
|
|
|
|
BOOST_TEST(n3.find() == std::string("P"));
|
|
|
|
BOOST_TEST(n4.find() == std::string("P"));
|
|
|
|
BOOST_TEST(n5.find() == std::string("P"));
|
|
|
|
BOOST_TEST(q12.min_prio() == 5);
|
|
|
|
BOOST_TEST(q12.min_elem() == 'a');
|
|
|
|
BOOST_TEST(q345.min_prio() == 2);
|
|
|
|
BOOST_TEST(q345.min_elem() == 'c');
|
|
|
|
|
|
|
|
q12.split();
|
|
|
|
BOOST_TEST(n1.find() == std::string("A"));
|
|
|
|
BOOST_TEST(n2.find() == std::string("B"));
|
|
|
|
|
|
|
|
q345.split();
|
|
|
|
BOOST_TEST(n3.find() == std::string("C"));
|
|
|
|
BOOST_TEST(n4.find() == std::string("D"));
|
|
|
|
BOOST_TEST(n5.find() == std::string("E"));
|
|
|
|
BOOST_TEST(q3.min_prio() == 2);
|
|
|
|
BOOST_TEST(q3.min_elem() == 'c');
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_AUTO_TEST_CASE(test_medium)
|
2023-06-16 19:55:43 +02:00
|
|
|
{
|
2024-11-08 18:38:20 +01:00
|
|
|
using Queue = ConcatenableQueue<int, char, char>;
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-16 23:18:09 +01:00
|
|
|
std::vector<char> queue_names(19);
|
|
|
|
for (int i = 0; i < 14; i++) {
|
|
|
|
queue_names[i] = 'A' + i;
|
|
|
|
}
|
|
|
|
queue_names[14] = 'P';
|
|
|
|
queue_names[15] = 'Q';
|
|
|
|
queue_names[16] = 'R';
|
|
|
|
queue_names[17] = 'S';
|
|
|
|
queue_names[18] = 'Z';
|
|
|
|
|
|
|
|
std::vector<Queue> queues(queue_names.begin(), queue_names.end());
|
2024-11-08 18:38:20 +01:00
|
|
|
Queue::Node nodes[14];
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
int prios[14] = {3, 8, 6, 2, 9, 4, 6, 8, 1, 5, 9, 4, 7, 8};
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
auto min_prio = [&prios](int begin, int end) -> int {
|
|
|
|
int p = begin;
|
|
|
|
int m = prios[p];
|
|
|
|
++p;
|
|
|
|
while (p != end) {
|
|
|
|
m = std::min(m, prios[p]);
|
|
|
|
++p;
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
2024-11-08 18:38:20 +01:00
|
|
|
return m;
|
|
|
|
};
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 0; i < 14; i++) {
|
2024-11-16 23:18:09 +01:00
|
|
|
BOOST_TEST(queues[i].name() == 'A' + i);
|
2024-11-08 18:38:20 +01:00
|
|
|
queues[i].insert(&nodes[i], prios[i], 'a' + i);
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
auto m14 = {&queues[0], &queues[1]};
|
|
|
|
queues[14].merge(m14.begin(), m14.end());
|
2024-11-16 23:18:09 +01:00
|
|
|
BOOST_TEST(queues[14].name() == 'P');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(queues[14].min_prio() == min_prio(0, 2));
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
auto m15 = {&queues[2], &queues[3], &queues[4]};
|
|
|
|
queues[15].merge(m15.begin(), m15.end());
|
2024-11-16 23:18:09 +01:00
|
|
|
BOOST_TEST(queues[15].name() == 'Q');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(queues[15].min_prio() == min_prio(2, 5));
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
auto m16 = {&queues[5], &queues[6], &queues[7], &queues[8]};
|
|
|
|
queues[16].merge(m16.begin(), m16.end());
|
2024-11-16 23:18:09 +01:00
|
|
|
BOOST_TEST(queues[16].name() == 'R');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(queues[16].min_prio() == min_prio(5, 9));
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
auto m17 = {&queues[9], &queues[10], &queues[11], &queues[12],
|
|
|
|
&queues[13]};
|
|
|
|
queues[17].merge(m17.begin(), m17.end());
|
2024-11-16 23:18:09 +01:00
|
|
|
BOOST_TEST(queues[17].name() == 'S');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(queues[17].min_prio() == min_prio(9, 14));
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
BOOST_TEST(nodes[i].find() == 'P');
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 2; i < 5; i++) {
|
|
|
|
BOOST_TEST(nodes[i].find() == 'Q');
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 5; i < 9; i++) {
|
|
|
|
BOOST_TEST(nodes[i].find() == 'R');
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 9; i < 14; i++) {
|
|
|
|
BOOST_TEST(nodes[i].find() == 'S');
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
auto m18 = {&queues[14], &queues[15], &queues[16], &queues[17]};
|
|
|
|
queues[18].merge(m18.begin(), m18.end());
|
2024-11-16 23:18:09 +01:00
|
|
|
BOOST_TEST(queues[18].name() == 'Z');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(queues[18].min_prio() == 1);
|
|
|
|
BOOST_TEST(queues[18].min_elem() == 'i');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 0; i < 14; i++) {
|
|
|
|
BOOST_TEST(nodes[i].find() == 'Z');
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
prios[8] = 5;
|
|
|
|
nodes[8].set_prio(prios[8]);
|
|
|
|
BOOST_TEST(queues[18].min_prio() == 2);
|
|
|
|
BOOST_TEST(queues[18].min_elem() == 'd');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
queues[18].split();
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
BOOST_TEST(nodes[i].find() == 'P');
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 2; i < 5; i++) {
|
|
|
|
BOOST_TEST(nodes[i].find() == 'Q');
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 5; i < 9; i++) {
|
|
|
|
BOOST_TEST(nodes[i].find() == 'R');
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 9; i < 14; i++) {
|
|
|
|
BOOST_TEST(nodes[i].find() == 'S');
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(queues[14].min_prio() == min_prio(0, 2));
|
|
|
|
BOOST_TEST(queues[15].min_prio() == min_prio(2, 5));
|
|
|
|
BOOST_TEST(queues[16].min_prio() == min_prio(5, 9));
|
|
|
|
BOOST_TEST(queues[17].min_prio() == min_prio(9, 14));
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 14; i < 18; i++) {
|
|
|
|
queues[i].split();
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
for (int i = 0; i < 14; i++) {
|
|
|
|
BOOST_TEST(nodes[i].find() == 'A' + i);
|
|
|
|
BOOST_TEST(queues[i].min_prio() == prios[i]);
|
|
|
|
BOOST_TEST(queues[i].min_elem() == 'a' + i);
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(test_random)
|
|
|
|
{
|
2024-11-08 18:38:20 +01:00
|
|
|
using Queue = ConcatenableQueue<double, int, int>;
|
|
|
|
|
|
|
|
constexpr int NUM_NODES = 4000;
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
std::mt19937 rng(23456);
|
2024-11-08 18:38:20 +01:00
|
|
|
std::uniform_real_distribution<> prio_distribution;
|
|
|
|
std::uniform_int_distribution<> node_distribution(0, NUM_NODES - 1);
|
|
|
|
|
|
|
|
double prios[NUM_NODES];
|
|
|
|
Queue::Node nodes[NUM_NODES];
|
|
|
|
std::unordered_map<int, std::unique_ptr<Queue>> queues;
|
|
|
|
std::unordered_map<int, std::set<int>> queue_nodes;
|
|
|
|
std::unordered_map<int, std::set<int>> queue_subs;
|
|
|
|
std::set<int> live_queues;
|
|
|
|
std::set<int> live_merged_queues;
|
|
|
|
|
|
|
|
// Make trivial queues.
|
|
|
|
for (int i = 0; i < NUM_NODES; i++) {
|
|
|
|
int name = 10000 + i;
|
|
|
|
prios[i] = prio_distribution(rng);
|
2024-11-16 23:18:09 +01:00
|
|
|
queues[name] = std::unique_ptr<Queue>(new Queue(name));
|
2024-11-08 18:38:20 +01:00
|
|
|
queues[name]->insert(&nodes[i], prios[i], i);
|
|
|
|
queue_nodes[name].insert(i);
|
|
|
|
live_queues.insert(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run modifications.
|
|
|
|
for (int i = 0; i < 4000; i++) {
|
|
|
|
|
|
|
|
// Find top-level queue of few nodes.
|
|
|
|
for (int k = 0; k < 200; k++) {
|
|
|
|
int t = node_distribution(rng);
|
|
|
|
int name = nodes[t].find();
|
|
|
|
BOOST_TEST(queue_nodes[name].count(t) == 1);
|
|
|
|
}
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
// Change priority of a few nodes.
|
|
|
|
for (int k = 0; k < 10; k++) {
|
|
|
|
int t = node_distribution(rng);
|
|
|
|
int name = nodes[t].find();
|
|
|
|
BOOST_TEST(live_queues.count(name) == 1);
|
|
|
|
BOOST_TEST(queue_nodes[name].count(t) == 1);
|
|
|
|
BOOST_TEST(nodes[t].prio() == prios[t]);
|
|
|
|
double p = prio_distribution(rng);
|
|
|
|
prios[t] = p;
|
|
|
|
nodes[t].set_prio(p);
|
|
|
|
for (int tt : queue_nodes[name]) {
|
|
|
|
if (prios[tt] < p) {
|
|
|
|
t = tt;
|
|
|
|
p = prios[tt];
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
}
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(queues[name]->min_prio() == p);
|
|
|
|
BOOST_TEST(queues[name]->min_elem() == t);
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
if (live_queues.size() > 100) {
|
|
|
|
|
|
|
|
// Choose number of queues to merge between 2 and 100.
|
|
|
|
int k = std::uniform_int_distribution<>(2, 100)(rng);
|
|
|
|
k = std::uniform_int_distribution<>(2, k)(rng);
|
|
|
|
|
|
|
|
// Choose queues to merge.
|
|
|
|
std::vector<int> live_queue_vec(live_queues.begin(),
|
|
|
|
live_queues.end());
|
|
|
|
std::vector<int> sub_names;
|
|
|
|
std::vector<Queue*> sub_queues;
|
|
|
|
for (int ki = 0; ki < k; ki++) {
|
|
|
|
int t = std::uniform_int_distribution<>(
|
|
|
|
0, live_queue_vec.size() - 1)(rng);
|
|
|
|
int name = live_queue_vec[t];
|
|
|
|
sub_names.push_back(name);
|
|
|
|
sub_queues.push_back(queues[name].get());
|
|
|
|
live_queue_vec[t] = live_queue_vec.back();
|
|
|
|
live_queue_vec.pop_back();
|
|
|
|
live_queues.erase(name);
|
|
|
|
live_merged_queues.erase(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create new queue by merging selected queues.
|
|
|
|
int name = 20000 + i;
|
2024-11-16 23:18:09 +01:00
|
|
|
queues[name] = std::unique_ptr<Queue>(new Queue(name));
|
2024-11-08 18:38:20 +01:00
|
|
|
queues[name]->merge(sub_queues.begin(), sub_queues.end());
|
|
|
|
for (int nn : sub_names) {
|
|
|
|
queue_nodes[name].insert(queue_nodes[nn].begin(),
|
|
|
|
queue_nodes[nn].end());
|
|
|
|
}
|
|
|
|
queue_subs[name].insert(sub_names.begin(), sub_names.end());
|
|
|
|
live_queues.insert(name);
|
|
|
|
live_merged_queues.insert(name);
|
|
|
|
|
|
|
|
// Check new queue.
|
|
|
|
{
|
|
|
|
double p = 2;
|
|
|
|
int t = 0;
|
|
|
|
for (int tt : queue_nodes[name]) {
|
|
|
|
if (prios[tt] < p) {
|
|
|
|
t = tt;
|
|
|
|
p = prios[tt];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOOST_TEST(queues[name]->min_prio() == p);
|
|
|
|
BOOST_TEST(queues[name]->min_elem() == t);
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
if ((live_queues.size() <= 100)
|
|
|
|
|| (live_merged_queues.size() >= 100)) {
|
|
|
|
|
|
|
|
// Choose a random queue to split.
|
|
|
|
std::vector<int> live_queue_vec(live_merged_queues.begin(),
|
|
|
|
live_merged_queues.end());
|
|
|
|
int k = std::uniform_int_distribution<>(
|
|
|
|
0, live_queue_vec.size() - 1)(rng);
|
|
|
|
int name = live_queue_vec[k];
|
|
|
|
|
|
|
|
queues[name]->split();
|
|
|
|
|
|
|
|
for (int nn : queue_subs[name]) {
|
|
|
|
// Check reconstructed sub-queue.
|
|
|
|
double p = 2;
|
|
|
|
int t = 0;
|
|
|
|
for (int tt : queue_nodes[nn]) {
|
|
|
|
if (prios[tt] < p) {
|
|
|
|
t = tt;
|
|
|
|
p = prios[tt];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOOST_TEST(queues[nn]->min_prio() == p);
|
|
|
|
BOOST_TEST(queues[nn]->min_elem() == t);
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
// Mark sub-queue as live.
|
|
|
|
live_queues.insert(nn);
|
|
|
|
if (queue_subs.count(nn) == 1) {
|
|
|
|
live_merged_queues.insert(nn);
|
|
|
|
}
|
|
|
|
}
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
live_merged_queues.erase(name);
|
|
|
|
live_queues.erase(name);
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
queues.erase(name);
|
|
|
|
queue_nodes.erase(name);
|
|
|
|
queue_subs.erase(name);
|
2023-06-16 19:55:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|
|
|
|
|
|
|
|
|
|
|
|
/* ********** Test PriorityQueue ********** */
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_SUITE(test_priority_queue)
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(test_empty)
|
|
|
|
{
|
|
|
|
using Queue = PriorityQueue<int, std::string>;
|
|
|
|
Queue q;
|
|
|
|
BOOST_TEST(q.empty() == true);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(test_single)
|
|
|
|
{
|
|
|
|
using Queue = PriorityQueue<int, std::string>;
|
|
|
|
Queue q;
|
|
|
|
|
|
|
|
Queue::Node n1;
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(n1.valid() == false);
|
|
|
|
|
2023-06-16 19:55:43 +02:00
|
|
|
q.insert(&n1, 5, "a");
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(n1.valid() == true);
|
|
|
|
BOOST_TEST(n1.prio() == 5);
|
2023-06-16 19:55:43 +02:00
|
|
|
BOOST_TEST(q.empty() == false);
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 5);
|
|
|
|
BOOST_TEST(q.min_elem() == std::string("a"));
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
q.set_prio(&n1, 3);
|
|
|
|
BOOST_TEST(n1.prio() == 3);
|
|
|
|
BOOST_TEST(q.min_prio() == 3);
|
|
|
|
BOOST_TEST(q.min_elem() == std::string("a"));
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.remove(&n1);
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(n1.valid() == false);
|
2023-06-16 19:55:43 +02:00
|
|
|
BOOST_TEST(q.empty() == true);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(test_simple)
|
|
|
|
{
|
|
|
|
using Queue = PriorityQueue<int, char>;
|
|
|
|
Queue q;
|
|
|
|
Queue::Node nodes[10];
|
|
|
|
|
|
|
|
q.insert(&nodes[0], 9, 'a');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 9);
|
|
|
|
BOOST_TEST(q.min_elem() == 'a');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.insert(&nodes[1], 4, 'b');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
|
|
BOOST_TEST(q.min_elem() == 'b');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.insert(&nodes[2], 7, 'c');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
|
|
BOOST_TEST(q.min_elem() == 'b');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.insert(&nodes[3], 5, 'd');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
|
|
BOOST_TEST(q.min_elem() == 'b');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.insert(&nodes[4], 8, 'e');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
|
|
BOOST_TEST(q.min_elem() == 'b');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.insert(&nodes[5], 6, 'f');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
|
|
BOOST_TEST(q.min_elem() == 'b');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.insert(&nodes[6], 4, 'g');
|
|
|
|
q.insert(&nodes[7], 5, 'h');
|
|
|
|
q.insert(&nodes[8], 2, 'i');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 2);
|
|
|
|
BOOST_TEST(q.min_elem() == 'i');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.insert(&nodes[9], 6, 'j');
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 2);
|
|
|
|
BOOST_TEST(q.min_elem() == 'i');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
q.set_prio(&nodes[2], 1);
|
|
|
|
BOOST_TEST(q.min_prio() == 1);
|
|
|
|
BOOST_TEST(q.min_elem() == 'c');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
q.set_prio(&nodes[4], 3);
|
|
|
|
BOOST_TEST(q.min_prio() == 1);
|
|
|
|
BOOST_TEST(q.min_elem() == 'c');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.remove(&nodes[2]);
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 2);
|
|
|
|
BOOST_TEST(q.min_elem() == 'i');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.remove(&nodes[8]);
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 3);
|
|
|
|
BOOST_TEST(q.min_elem() == 'e');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.remove(&nodes[4]);
|
|
|
|
q.remove(&nodes[1]);
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
|
|
BOOST_TEST(q.min_elem() == 'g');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.remove(&nodes[3]);
|
|
|
|
q.remove(&nodes[9]);
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 4);
|
|
|
|
BOOST_TEST(q.min_elem() == 'g');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
q.remove(&nodes[6]);
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_TEST(q.min_prio() == 5);
|
|
|
|
BOOST_TEST(q.min_elem() == 'h');
|
2023-06-16 19:55:43 +02:00
|
|
|
|
|
|
|
BOOST_TEST(q.empty() == false);
|
|
|
|
q.clear();
|
|
|
|
BOOST_TEST(q.empty() == true);
|
|
|
|
}
|
|
|
|
|
2024-11-08 18:38:20 +01:00
|
|
|
BOOST_AUTO_TEST_CASE(test_increase_prio)
|
|
|
|
{
|
|
|
|
using Queue = 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);
|
|
|
|
}
|
|
|
|
|
2023-06-16 19:55:43 +02:00
|
|
|
BOOST_AUTO_TEST_CASE(test_random)
|
|
|
|
{
|
|
|
|
using Queue = 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]() {
|
2024-11-08 18:38:20 +01:00
|
|
|
int min_prio = q.min_prio();
|
|
|
|
int min_data = q.min_elem();
|
2023-06-16 19:55:43 +02:00
|
|
|
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]);
|
2024-11-08 18:38:20 +01:00
|
|
|
prio = std::uniform_int_distribution<>(0, 1000000)(rng);
|
|
|
|
q.set_prio(node, prio);
|
2023-06-16 19:55:43 +02:00
|
|
|
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()
|