661 lines
17 KiB
C++
661 lines
17 KiB
C++
/*
|
|
* 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 <map>
|
|
#include <memory>
|
|
#include <random>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#define BOOST_TEST_MODULE datastruct
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
#include "datastruct.h"
|
|
|
|
|
|
/* ********** Test DisjointSetNode ********** */
|
|
|
|
BOOST_AUTO_TEST_SUITE(test_disjoint_set)
|
|
|
|
BOOST_AUTO_TEST_CASE(test_single)
|
|
{
|
|
using Node = DisjointSetNode<int>;
|
|
Node a(1);
|
|
BOOST_TEST(a.find() == 1);
|
|
a.set_label(2);
|
|
BOOST_TEST(a.find() == 2);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_simple)
|
|
{
|
|
using Node = DisjointSetNode<int>;
|
|
Node a(1);
|
|
Node b(2);
|
|
Node c(3);
|
|
Node* m = a.merge(&b);
|
|
m->set_label(10);
|
|
BOOST_TEST(a.find() == 10);
|
|
BOOST_TEST(b.find() == 10);
|
|
BOOST_TEST(c.find() == 3);
|
|
m = m->merge(&c);
|
|
m->set_label(11);
|
|
BOOST_TEST(a.find() == 11);
|
|
BOOST_TEST(c.find() == 11);
|
|
a.detach(1);
|
|
b.detach(2);
|
|
c.detach(3);
|
|
BOOST_TEST(a.find() == 1);
|
|
BOOST_TEST(b.find() == 2);
|
|
BOOST_TEST(c.find() == 3);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_multilevel)
|
|
{
|
|
using Node = DisjointSetNode<int>;
|
|
|
|
std::unique_ptr<Node> nodes[27];
|
|
for (int i = 0; i < 27; ++i) {
|
|
nodes[i].reset(new Node(i));
|
|
}
|
|
|
|
std::vector<Node*> level1;
|
|
for (int i = 0; i < 9; ++i) {
|
|
Node* m = nodes[3*i].get();
|
|
for (int k = 1; k < 3; ++k) {
|
|
m = m->merge(nodes[3*i+k].get());
|
|
}
|
|
m->set_label(100 + i);
|
|
level1.push_back(m);
|
|
}
|
|
|
|
std::vector<Node*> level2;
|
|
for (int i = 0; i < 3; ++i) {
|
|
Node* m = level1[3*i];
|
|
for (int k = 1; k < 3; ++k) {
|
|
m = m->merge(level1[3*i+k]);
|
|
}
|
|
m->set_label(200 + i);
|
|
level2.push_back(m);
|
|
}
|
|
|
|
Node* m = level2[0];
|
|
for (int k = 1; k < 3; ++k) {
|
|
m = m->merge(level2[k]);
|
|
}
|
|
m->set_label(300);
|
|
|
|
for (int i = 0; i < 27; ++i) {
|
|
BOOST_TEST(nodes[i]->find() == 300);
|
|
}
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
level2[i]->detach(200 + i);
|
|
}
|
|
|
|
for (int i = 0; i < 27; ++i) {
|
|
BOOST_TEST(nodes[i]->find() == 200 + i / 9);
|
|
}
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
level1[i]->detach(100 + i);
|
|
}
|
|
|
|
for (int i = 0; i < 18; ++i) {
|
|
BOOST_TEST(nodes[i]->find() == 100 + i / 3);
|
|
}
|
|
for (int i = 18; i < 27; ++i) {
|
|
BOOST_TEST(nodes[i]->find() == 202);
|
|
}
|
|
|
|
for (int i = 6; i < 9; ++i) {
|
|
level1[i]->detach(100 + i);
|
|
}
|
|
|
|
for (int i = 0; i < 27; ++i) {
|
|
BOOST_TEST(nodes[i]->find() == 100 + i / 3);
|
|
}
|
|
|
|
for (int i = 6; i < 27; ++i) {
|
|
nodes[i]->detach(i);
|
|
}
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
BOOST_TEST(nodes[i]->find() == 100 + i / 3);
|
|
}
|
|
for (int i = 6; i < 27; ++i) {
|
|
BOOST_TEST(nodes[i]->find() == i);
|
|
}
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
nodes[i]->detach(i);
|
|
}
|
|
|
|
for (int i = 0; i < 27; ++i) {
|
|
BOOST_TEST(nodes[i]->find() == i);
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_random)
|
|
{
|
|
using Node = DisjointSetNode<int>;
|
|
|
|
std::mt19937 rng(12345);
|
|
|
|
const int num_nodes = 1000;
|
|
std::unique_ptr<Node> nodes[num_nodes];
|
|
for (int i = 0; i < num_nodes; ++i) {
|
|
nodes[i].reset(new Node(i));
|
|
}
|
|
|
|
std::unordered_map<int, Node*> blossoms;
|
|
std::unordered_map<int, std::vector<int>> sub_blossoms;
|
|
std::vector<int> top_blossoms;
|
|
|
|
for (int i = 0; i < num_nodes; ++i) {
|
|
blossoms[i] = nodes[i].get();
|
|
top_blossoms.push_back(i);
|
|
}
|
|
|
|
int next_blossom = num_nodes;
|
|
|
|
auto make_blossom = [&]() {
|
|
int b = next_blossom;
|
|
++next_blossom;
|
|
|
|
int nsub = 1 + 2 * std::uniform_int_distribution<>(1, 4)(rng);
|
|
std::vector<int> subs(nsub);
|
|
|
|
for (int i = 0; i < nsub; ++i) {
|
|
int p = std::uniform_int_distribution<>(0, top_blossoms.size() - 1)(rng);
|
|
subs[i] = top_blossoms[p];
|
|
top_blossoms.erase(top_blossoms.begin() + p);
|
|
}
|
|
|
|
Node *m = blossoms[subs[0]];
|
|
for (int i = 1; i < nsub; ++i) {
|
|
m = m->merge(blossoms[subs[i]]);
|
|
}
|
|
m->set_label(b);
|
|
|
|
blossoms[b] = m;
|
|
sub_blossoms[b] = std::move(subs);
|
|
top_blossoms.push_back(b);
|
|
};
|
|
|
|
auto expand_blossom = [&](int b) {
|
|
top_blossoms.erase(
|
|
std::find(top_blossoms.begin(), top_blossoms.end(), b));
|
|
for (int t : sub_blossoms[b]) {
|
|
blossoms[t]->detach(t);
|
|
top_blossoms.push_back(t);
|
|
}
|
|
blossoms.erase(b);
|
|
sub_blossoms.erase(b);
|
|
};
|
|
|
|
auto check_membership = [&](int b, int label) {
|
|
std::vector<int> q;
|
|
q.push_back(b);
|
|
while (! q.empty()) {
|
|
b = q.back();
|
|
q.pop_back();
|
|
if (b < num_nodes) {
|
|
BOOST_TEST(nodes[b]->find() == label);
|
|
} else {
|
|
for (int t : sub_blossoms[b]) {
|
|
q.push_back(t);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
for (int k = 0; k < 100; ++k) {
|
|
make_blossom();
|
|
}
|
|
|
|
for (int b : top_blossoms) {
|
|
check_membership(b, b);
|
|
}
|
|
|
|
std::vector<int> top_groups;
|
|
for (int b : top_blossoms) {
|
|
if (b >= num_nodes) {
|
|
top_groups.push_back(b);
|
|
}
|
|
}
|
|
std::shuffle(top_groups.begin(), top_groups.end(), rng);
|
|
for (int k = 0; k < 50; ++k) {
|
|
expand_blossom(top_groups[k]);
|
|
}
|
|
top_groups.clear();
|
|
|
|
for (int b : top_blossoms) {
|
|
check_membership(b, b);
|
|
}
|
|
|
|
for (int k = 0; k < 50; ++k) {
|
|
make_blossom();
|
|
}
|
|
|
|
for (int b : top_blossoms) {
|
|
check_membership(b, b);
|
|
}
|
|
|
|
for (int b : top_blossoms) {
|
|
if (b >= num_nodes) {
|
|
top_groups.push_back(b);
|
|
}
|
|
}
|
|
std::shuffle(top_groups.begin(), top_groups.end(), rng);
|
|
for (int b : top_groups) {
|
|
expand_blossom(b);
|
|
}
|
|
|
|
for (int b : top_blossoms) {
|
|
check_membership(b, b);
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|
|
|
|
|
|
/* ********** Test SplittablePriorityQueue ********** */
|
|
|
|
template <typename PrioType, typename DataType>
|
|
static void check_min_elem(const std::pair<PrioType, DataType>& pair,
|
|
PrioType prio,
|
|
const DataType& data)
|
|
{
|
|
BOOST_TEST(pair.first == prio);
|
|
BOOST_TEST(pair.second == data);
|
|
}
|
|
|
|
|
|
BOOST_AUTO_TEST_SUITE(test_splittable_queue)
|
|
|
|
BOOST_AUTO_TEST_CASE(test_single)
|
|
{
|
|
using Queue = SplittablePriorityQueue<int, int>;
|
|
Queue q;
|
|
|
|
BOOST_TEST(q.empty() == true);
|
|
|
|
Queue::Node n;
|
|
q.insert(&n, 3, 4, 101);
|
|
|
|
BOOST_TEST(q.empty() == false);
|
|
check_min_elem(q.find_min(), 4, 101);
|
|
|
|
q.update(&n, 5, 102);
|
|
check_min_elem(q.find_min(), 4, 101);
|
|
|
|
q.update(&n, 3, 103);
|
|
check_min_elem(q.find_min(), 3, 103);
|
|
|
|
q.clear();
|
|
BOOST_TEST(q.empty() == true);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_simple)
|
|
{
|
|
using Queue = SplittablePriorityQueue<int, std::string>;
|
|
Queue q;
|
|
Queue::Node n1, n2, n3, n4, n5, nx;
|
|
|
|
q.insert(&n1, 1, 5, "a");
|
|
q.insert(&n2, 2, 6, "b");
|
|
q.insert(&n3, 3, 7, "c");
|
|
q.insert(&n4, 4, 4, "d");
|
|
q.insert(&n5, 5, 3, "e");
|
|
check_min_elem(q.find_min(), 3, std::string("e"));
|
|
|
|
q.update(&n1, 4, "f");
|
|
check_min_elem(q.find_min(), 3, std::string("e"));
|
|
|
|
q.update(&n3, 2, "h");
|
|
check_min_elem(q.find_min(), 2, std::string("h"));
|
|
|
|
Queue q2 = q.split(3);
|
|
check_min_elem(q.find_min(), 4, std::string("f"));
|
|
check_min_elem(q2.find_min(), 2, std::string("h"));
|
|
|
|
q.insert(&nx, 3, 1, "x");
|
|
check_min_elem(q.find_min(), 1, std::string("x"));
|
|
check_min_elem(q2.find_min(), 2, std::string("h"));
|
|
|
|
q.clear();
|
|
q2.clear();
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_split_empty)
|
|
{
|
|
using Queue = SplittablePriorityQueue<int, std::string>;
|
|
Queue q;
|
|
Queue q2 = q.split(10);
|
|
BOOST_TEST(q.empty() == true);
|
|
BOOST_TEST(q2.empty() == true);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_split_oneway)
|
|
{
|
|
using Queue = SplittablePriorityQueue<int, std::string>;
|
|
Queue q;
|
|
Queue::Node n4, n5, n6;
|
|
q.insert(&n4, 4, 3, "a");
|
|
q.insert(&n5, 5, 4, "b");
|
|
q.insert(&n6, 6, 2, "c");
|
|
Queue q2 = q.split(7);
|
|
BOOST_TEST(q.empty() == false);
|
|
BOOST_TEST(q2.empty() == true);
|
|
check_min_elem(q.find_min(), 2, std::string("c"));
|
|
q.clear();
|
|
|
|
q.insert(&n4, 4, 3, "a");
|
|
q.insert(&n5, 5, 4, "b");
|
|
q.insert(&n6, 6, 2, "c");
|
|
q2 = q.split(4);
|
|
BOOST_TEST(q.empty() == true);
|
|
BOOST_TEST(q2.empty() == false);
|
|
check_min_elem(q2.find_min(), 2, std::string("c"));
|
|
q2.clear();
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_larger)
|
|
{
|
|
using Queue = SplittablePriorityQueue<int, std::string>;
|
|
Queue q;
|
|
Queue::Node nodes[15];
|
|
|
|
q.insert(&nodes[7], 7, 5, "h");
|
|
q.insert(&nodes[6], 6, 4, "g");
|
|
q.insert(&nodes[8], 8, 2, "i");
|
|
q.insert(&nodes[5], 5, 4, "f");
|
|
q.insert(&nodes[9], 9, 6, "j");
|
|
q.insert(&nodes[4], 4, 8, "e");
|
|
q.insert(&nodes[10], 10, 4, "k");
|
|
q.insert(&nodes[3], 3, 5, "d");
|
|
q.insert(&nodes[11], 11, 6, "l");
|
|
q.insert(&nodes[2], 2, 7, "c");
|
|
q.insert(&nodes[12], 12, 8, "m");
|
|
q.insert(&nodes[1], 1, 3, "b");
|
|
q.insert(&nodes[13], 13, 1, "n");
|
|
q.insert(&nodes[0], 0, 9, "a");
|
|
q.insert(&nodes[14], 14, 7, "o");
|
|
|
|
check_min_elem(q.find_min(), 1, std::string("n"));
|
|
|
|
Queue q2 = q.split(10);
|
|
check_min_elem(q.find_min(), 2, std::string("i"));
|
|
check_min_elem(q2.find_min(), 1, std::string("n"));
|
|
|
|
Queue q1 = q.split(5);
|
|
check_min_elem(q.find_min(), 3, std::string("b"));
|
|
check_min_elem(q1.find_min(), 2, std::string("i"));
|
|
check_min_elem(q2.find_min(), 1, std::string("n"));
|
|
|
|
q.clear();
|
|
q1.clear();
|
|
q2.clear();
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_random)
|
|
{
|
|
using Queue = SplittablePriorityQueue<int, int>;
|
|
|
|
std::mt19937 rng(23456);
|
|
std::uniform_int_distribution<> index_distribution(0, 1000000);
|
|
std::uniform_int_distribution<> prio_distribution(0, 1000000);
|
|
|
|
Queue q;
|
|
std::map<int, std::tuple<std::unique_ptr<Queue::Node>, int, int>> elems;
|
|
int next_data = 1;
|
|
|
|
for (int i = 0; i < 200; ++i) {
|
|
|
|
// Insert stuff into the queue.
|
|
for (int k = 0; k < 1000; ++k) {
|
|
int idx = index_distribution(rng);
|
|
int prio = prio_distribution(rng);
|
|
int data = next_data;
|
|
++next_data;
|
|
auto it = elems.find(idx);
|
|
if (it != elems.end()) {
|
|
auto& v = it->second;
|
|
Queue::Node* nptr = std::get<0>(v).get();
|
|
int pprio = std::get<1>(v);
|
|
q.update(nptr, prio, data);
|
|
if (prio < pprio) {
|
|
std::get<1>(v) = prio;
|
|
std::get<2>(v) = data;
|
|
}
|
|
} else {
|
|
std::unique_ptr<Queue::Node> nptr(new Queue::Node);
|
|
q.insert(nptr.get(), idx, prio, data);
|
|
elems[idx] = std::make_tuple(std::move(nptr), prio, data);
|
|
}
|
|
}
|
|
|
|
// Check min element.
|
|
int min_prio = INT_MAX;
|
|
int min_data = 0;
|
|
for (const auto& v : elems) {
|
|
int prio = std::get<1>(v.second);
|
|
int data = std::get<2>(v.second);
|
|
if (prio < min_prio) {
|
|
min_prio = prio;
|
|
min_data = data;
|
|
}
|
|
}
|
|
|
|
check_min_elem(q.find_min(), min_prio, min_data);
|
|
|
|
// Split the queue.
|
|
int threshold = index_distribution(rng);
|
|
Queue q2 = q.split(threshold);
|
|
|
|
// Keep one queue and discard the other.
|
|
if (rng() % 2 == 0) {
|
|
q.clear();
|
|
q = std::move(q2);
|
|
elems.erase(elems.begin(), elems.lower_bound(threshold));
|
|
} else {
|
|
q2.clear();
|
|
elems.erase(elems.lower_bound(threshold), elems.end());
|
|
}
|
|
|
|
// Check min element.
|
|
min_prio = INT_MAX;
|
|
min_data = 0;
|
|
for (const auto& v : elems) {
|
|
int prio = std::get<1>(v.second);
|
|
int data = std::get<2>(v.second);
|
|
if (prio < min_prio) {
|
|
min_prio = prio;
|
|
min_data = data;
|
|
}
|
|
}
|
|
|
|
if (min_prio < INT_MAX) {
|
|
check_min_elem(q.find_min(), min_prio, min_data);
|
|
}
|
|
}
|
|
|
|
q.clear();
|
|
}
|
|
|
|
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;
|
|
q.insert(&n1, 5, "a");
|
|
|
|
BOOST_TEST(q.empty() == false);
|
|
check_min_elem(q.find_min(), 5, std::string("a"));
|
|
|
|
q.update(&n1, 3, "a");
|
|
check_min_elem(q.find_min(), 3, std::string("a"));
|
|
|
|
q.remove(&n1);
|
|
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');
|
|
check_min_elem(q.find_min(), 9, 'a');
|
|
|
|
q.insert(&nodes[1], 4, 'b');
|
|
check_min_elem(q.find_min(), 4, 'b');
|
|
|
|
q.insert(&nodes[2], 7, 'c');
|
|
check_min_elem(q.find_min(), 4, 'b');
|
|
|
|
q.insert(&nodes[3], 5, 'd');
|
|
check_min_elem(q.find_min(), 4, 'b');
|
|
|
|
q.insert(&nodes[4], 8, 'e');
|
|
check_min_elem(q.find_min(), 4, 'b');
|
|
|
|
q.insert(&nodes[5], 6, 'f');
|
|
check_min_elem(q.find_min(), 4, 'b');
|
|
|
|
q.insert(&nodes[6], 4, 'g');
|
|
q.insert(&nodes[7], 5, 'h');
|
|
q.insert(&nodes[8], 2, 'i');
|
|
check_min_elem(q.find_min(), 2, 'i');
|
|
|
|
q.insert(&nodes[9], 6, 'j');
|
|
check_min_elem(q.find_min(), 2, 'i');
|
|
|
|
q.update(&nodes[2], 1, 'c');
|
|
check_min_elem(q.find_min(), 1, 'c');
|
|
|
|
q.update(&nodes[4], 3, 'e');
|
|
check_min_elem(q.find_min(), 1, 'c');
|
|
|
|
q.remove(&nodes[2]);
|
|
check_min_elem(q.find_min(), 2, 'i');
|
|
|
|
q.remove(&nodes[8]);
|
|
check_min_elem(q.find_min(), 3, 'e');
|
|
|
|
q.remove(&nodes[4]);
|
|
q.remove(&nodes[1]);
|
|
check_min_elem(q.find_min(), 4, 'g');
|
|
|
|
q.remove(&nodes[3]);
|
|
q.remove(&nodes[9]);
|
|
check_min_elem(q.find_min(), 4, 'g');
|
|
|
|
q.remove(&nodes[6]);
|
|
check_min_elem(q.find_min(), 5, 'h');
|
|
|
|
BOOST_TEST(q.empty() == false);
|
|
q.clear();
|
|
BOOST_TEST(q.empty() == true);
|
|
}
|
|
|
|
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]() {
|
|
int min_prio, min_data;
|
|
std::tie(min_prio, min_data) = q.find_min();
|
|
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]);
|
|
int data = std::get<2>(elems[p]);
|
|
prio = std::uniform_int_distribution<>(0, prio)(rng);
|
|
q.update(node, prio, data);
|
|
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()
|