#include "../pool.hpp" #include "../tap.hpp" #include #include #include //----------------------------------------------------------------------------- void check_single (cruft::TAP::logger &tap) { // Ensure a single element doesn't break the circular linked list cruft::pool single(1); tap.expect_nothrow ([&] { single.deallocate (single.allocate ()); }, "single element acquire-release"); } //----------------------------------------------------------------------------- void check_unique_ptr (cruft::TAP::logger &tap) { constexpr std::size_t element_count = 1025; cruft::pool uintpool (element_count); std::set uintset; // Take all pointers out, checking they are unique, then replace for destruction. while (!uintpool.full ()) uintset.insert (uintpool.allocate ()); tap.expect_eq (uintset.size (), uintpool.capacity (), "extracted maximum elements"); for (auto i: uintset) uintpool.deallocate (i); tap.expect_eq (uintpool.size (), 0u, "re-inserted maximum elements"); uintset.clear (); // Do the above one more time to ensure that releasing works right while (!uintpool.full ()) uintset.insert (uintpool.allocate ()); tap.expect_eq (uintset.size (), uintpool.capacity (), "re-extracted maximum elements"); } //----------------------------------------------------------------------------- void check_keep_value (cruft::TAP::logger &tap) { // Ensure that items keep their values. cruft::pool uintpool(256); std::vector uintvector; uintvector.reserve(uintpool.capacity ()); // Give every item a unique value for (std::size_t i = 0; i < uintpool.capacity (); ++i) { std::size_t *item = uintpool.allocate (); *item = i; uintvector.push_back(item); } CHECK_EQ (uintvector.size (), uintpool.capacity ()); // Ensure they're all still present std::vector present(uintpool.capacity (), false); for (auto i = uintvector.begin (); i != uintvector.end (); ++i) { CHECK (**i < uintpool.capacity ()); CHECK (present[**i] != true); present[**i] = true; } // All must have been marked as present... tap.expect (std::find (present.begin (), present.end (), false) == present.end (), "values retained"); // Release all back into the pool for destruction //for (auto i = uintvector.begin (); i != uintvector.end (); ++i) // uintpool.release (*i); //uintvector.clear (); } //----------------------------------------------------------------------------- void check_keep_variadic_value (cruft::TAP::logger &tap) { struct foo_t { foo_t (uint64_t _a, uint64_t _b, uint64_t _c, uint64_t _d): a (_a), b (_b), c (_c), d (_d) { ; } uint64_t a, b, c, d; }; cruft::pool alloc (512); bool success = true; for (uint64_t a = 0; a < 8; ++a) for (uint64_t b = 0; b < 8; ++b) for (uint64_t c = 0; c < 8; ++c) { uint64_t d = (a << 24) | (b << 16) | (c << 8); auto ptr = alloc.construct (a, b, c, d); if (ptr->a != a || ptr->b != b || ptr->c != c || ptr->d != d) { success = false; goto done; } } done: tap.expect (success, "variadiac construction retains values"); } //----------------------------------------------------------------------------- void check_size_queries (cruft::TAP::logger &tap) { cruft::pool data (8); tap.expect_eq (data.size (), 0u, "initial size is zero"); tap.expect (data.empty (), "initial object is empty"); auto first = data.allocate (); tap.expect_eq (data.size (), 1u, "1 allocation has size of 1"); tap.expect (!data.empty (), "1 allocation is not empty"); data.deallocate (first); tap.expect (data.empty (), "full deallocation is empty"); } //----------------------------------------------------------------------------- int main (int, char **) { return cruft::TAP::logger::run ([] (auto &tap) { check_single (tap); check_unique_ptr (tap); check_keep_value (tap); check_keep_variadic_value (tap); check_size_queries (tap); }); }