#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 deque_item { }; 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); } }