libcruft-util/test/list/sort.cpp

90 lines
2.4 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
*/
#include "list/sort.hpp"
#include "random.hpp"
#include "tap.hpp"
#include "iterator/zip.hpp"
#include <list>
#include <vector>
#include <algorithm>
///////////////////////////////////////////////////////////////////////////////
template <std::size_t N, typename ...ArgsT>
static void
test_sort (
cruft::TAP::logger &tap,
std::vector<int> &&data,
char const (&fmt)[N],
ArgsT&&...args
) {
// Pre-allocate the array so that we don't get caught by pointer
// invalidation as we build the nodes.
std::vector<
cruft::list::node::compound<int>
> nodes (data.size ());
// Build the list and fold in the supplied data.
for (auto [node, value]: cruft::iterator::zip (nodes, data)) {
node.next = &node + 1;
node.data = value;
}
nodes.back ().next = nullptr;
// Actually do the sort and test the result.
auto head = cruft::list::sort (
&nodes.front (),
&nodes.back ()
);
tap.expect (
cruft::list::is_sorted (head),
fmt,
std::forward<ArgsT> (args)...
);
}
//-----------------------------------------------------------------------------
int main ()
{
cruft::TAP::logger tap;
// Try sorting a 'large' array of unique, but shuffled, contiguous integers.
{
// Don't use a power of two here. It won't exercise any edge cases in
// the splitting logic of some sorts (like merge).
static constexpr int COUNT = 500'000;
// Create a list of randomly distributed integers. Use a constant seed so
// we don't get randomised test results.
std::vector<int> data (COUNT);
std::iota (std::begin (data), std::end (data), 0);
std::shuffle (
std::begin (data),
std::end (data),
std::mt19937 {COUNT}
);
test_sort (tap, std::move (data), "sorting large unique and shuffled array");
}
// Try sorting a small array with identical elements
{
static constexpr int COUNT = 15;
std::vector<int> data (COUNT, COUNT);
test_sort (tap, std::move (data), "sorting small identical array");
}
return tap.status ();
}