#include #include #include #include #include #include #include using namespace pls::internal::data_structures; using namespace pls::internal::base; using namespace std; TEST_CASE("aligned stack stores objects correctly", "[internal/data_structures/aligned_stack.h]") { constexpr long data_size = 1024; char data[data_size]; aligned_stack stack{data, data_size}; SECTION("stack correctly pushes sub linesize objects") { std::array small_data_one{'a', 'b', 'c', 'd', 'e'}; std::array small_data_two{}; std::array small_data_three{'A'}; auto pointer_one = stack.push(small_data_one); auto pointer_two = stack.push(small_data_two); auto pointer_three = stack.push(small_data_three); REQUIRE(reinterpret_cast(pointer_one) % system_details::CACHE_LINE_SIZE == 0); REQUIRE(reinterpret_cast(pointer_two) % system_details::CACHE_LINE_SIZE == 0); REQUIRE(reinterpret_cast(pointer_three) % system_details::CACHE_LINE_SIZE == 0); } SECTION("stack correctly pushes above linesize objects") { std::array small_data_one{'a', 'b', 'c', 'd', 'e'}; std::array big_data_one{}; auto big_pointer_one = stack.push(big_data_one); auto small_pointer_one = stack.push(small_data_one); REQUIRE(reinterpret_cast(big_pointer_one) % system_details::CACHE_LINE_SIZE == 0); REQUIRE(reinterpret_cast(small_pointer_one) % system_details::CACHE_LINE_SIZE == 0); } SECTION("stack correctly stores and retrieves objects") { std::array data_one{'a', 'b', 'c', 'd', 'e'}; stack.push(data_one); auto retrieved_data = stack.pop>(); REQUIRE(retrieved_data == std::array{'a', 'b', 'c', 'd', 'e'}); } SECTION("stack can push and pop multiple times with correct alignment") { std::array small_data_one{'a', 'b', 'c', 'd', 'e'}; std::array small_data_two{}; std::array small_data_three{'A'}; auto pointer_one = stack.push(small_data_one); auto pointer_two = stack.push(small_data_two); auto pointer_three = stack.push(small_data_three); stack.pop(); stack.pop(); auto pointer_four = stack.push(small_data_two); auto pointer_five = stack.push(small_data_three); REQUIRE(reinterpret_cast(pointer_one) % system_details::CACHE_LINE_SIZE == 0); REQUIRE(reinterpret_cast(pointer_two) % system_details::CACHE_LINE_SIZE == 0); REQUIRE(reinterpret_cast(pointer_three) % system_details::CACHE_LINE_SIZE == 0); REQUIRE(reinterpret_cast(pointer_four) % system_details::CACHE_LINE_SIZE == 0); REQUIRE(reinterpret_cast(pointer_five) % system_details::CACHE_LINE_SIZE == 0); REQUIRE(pointer_four == pointer_two); REQUIRE(pointer_five == pointer_three); } } TEST_CASE("deque stores objects correctly", "[internal/data_structures/deque.h]") { class my_item : public locking_deque_item { }; locking_deque deque; my_item one, two, three; SECTION("add and remove items form the tail") { deque.push_tail(&one); deque.push_tail(&two); deque.push_tail(&three); REQUIRE(deque.pop_tail() == &three); REQUIRE(deque.pop_tail() == &two); REQUIRE(deque.pop_tail() == &one); } SECTION("handles getting empty by popping the tail correctly") { deque.push_tail(&one); REQUIRE(deque.pop_tail() == &one); deque.push_tail(&two); REQUIRE(deque.pop_tail() == &two); } SECTION("remove items form the head") { deque.push_tail(&one); deque.push_tail(&two); deque.push_tail(&three); REQUIRE(deque.pop_head() == &one); REQUIRE(deque.pop_head() == &two); REQUIRE(deque.pop_head() == &three); } SECTION("handles getting empty by popping the head correctly") { deque.push_tail(&one); REQUIRE(deque.pop_head() == &one); deque.push_tail(&two); REQUIRE(deque.pop_head() == &two); } SECTION("handles getting empty by popping the head and tail correctly") { deque.push_tail(&one); REQUIRE(deque.pop_tail() == &one); deque.push_tail(&two); REQUIRE(deque.pop_head() == &two); deque.push_tail(&three); REQUIRE(deque.pop_tail() == &three); } } TEST_CASE("work stealing deque stores objects correctly", "[internal/data_structures/aligned_stack.h]") { constexpr long data_size = 2 << 14; char data[data_size]; aligned_stack stack{data, data_size}; work_stealing_deque deque{&stack}; int one = 1, two = 2, three = 3, four = 4; SECTION("add and remove items form the tail") { deque.push_tail(one); deque.push_tail(two); deque.push_tail(three); REQUIRE(*deque.pop_tail() == three); REQUIRE(*deque.pop_tail() == two); REQUIRE(*deque.pop_tail() == one); } SECTION("handles getting empty by popping the tail correctly") { deque.push_tail(one); REQUIRE(*deque.pop_tail() == one); deque.push_tail(two); REQUIRE(*deque.pop_tail() == two); } SECTION("remove items form the head") { deque.push_tail(one); deque.push_tail(two); deque.push_tail(three); REQUIRE(*deque.pop_head() == one); REQUIRE(*deque.pop_head() == two); REQUIRE(*deque.pop_head() == three); } SECTION("handles getting empty by popping the head correctly") { deque.push_tail(one); REQUIRE(*deque.pop_head() == one); deque.push_tail(two); REQUIRE(*deque.pop_head() == two); } SECTION("handles getting empty by popping the head and tail correctly") { deque.push_tail(one); REQUIRE(*deque.pop_tail() == one); deque.push_tail(two); REQUIRE(*deque.pop_head() == two); deque.push_tail(three); REQUIRE(*deque.pop_tail() == three); } SECTION("handles jumps bigger 1 correctly") { deque.push_tail(one); deque.push_tail(two); REQUIRE(*deque.pop_tail() == two); deque.push_tail(three); deque.push_tail(four); REQUIRE(*deque.pop_head() == one); REQUIRE(*deque.pop_head() == three); REQUIRE(*deque.pop_head() == four); } SECTION("handles stack reset 1 correctly when emptied by tail") { deque.push_tail(one); auto state = deque.save_state(); deque.push_tail(two); REQUIRE(*deque.pop_tail() == two); deque.release_memory_until(state); REQUIRE(*deque.pop_tail() == one); deque.push_tail(three); deque.push_tail(four); REQUIRE(*deque.pop_head() == three); REQUIRE(*deque.pop_tail() == four); } SECTION("synces correctly") { } }