data_structures_test.cpp 3.81 KB
Newer Older
1
#include <catch.hpp>
2
#include <mutex>
3

4
#include "pls/internal/base/system_details.h"
5
#include "pls/internal/data_structures/aligned_stack.h"
6
#include "pls/internal/data_structures/bounded_trading_deque.h"
7

8
using namespace pls::internal::data_structures;
9 10 11
using namespace pls::internal::base;
using namespace std;

12 13 14
// Forward Declaration
void test_stack(aligned_stack &stack);

15 16 17
TEST_CASE("aligned stack stores objects correctly", "[internal/data_structures/aligned_stack.h]") {
  constexpr long data_size = 1024;

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
  SECTION("plain aligned stack") {
    char data[data_size];
    aligned_stack stack{data, data_size, data_size};

    test_stack(stack);
  }

  SECTION("static aligned stack") {
    static_aligned_stack<data_size> stack;

    test_stack(stack.get_stack());
  }

  SECTION("heap aligned stack") {
    heap_aligned_stack stack{data_size};

    test_stack(stack.get_stack());
  }
}

void test_stack(aligned_stack &stack) {
39 40 41 42 43
  SECTION("stack correctly pushes sub linesize objects") {
    std::array<char, 5> small_data_one{'a', 'b', 'c', 'd', 'e'};
    std::array<char, 64> small_data_two{};
    std::array<char, 1> small_data_three{'A'};

44 45 46
    auto pointer_one = stack.push<decltype(small_data_one)>(small_data_one);
    auto pointer_two = stack.push<decltype(small_data_two)>(small_data_two);
    auto pointer_three = stack.push<decltype(small_data_three)>(small_data_three);
47 48 49 50 51 52 53 54 55 56

    REQUIRE(reinterpret_cast<std::uintptr_t>(pointer_one) % system_details::CACHE_LINE_SIZE == 0);
    REQUIRE(reinterpret_cast<std::uintptr_t>(pointer_two) % system_details::CACHE_LINE_SIZE == 0);
    REQUIRE(reinterpret_cast<std::uintptr_t>(pointer_three) % system_details::CACHE_LINE_SIZE == 0);
  }

  SECTION("stack correctly pushes above linesize objects") {
    std::array<char, 5> small_data_one{'a', 'b', 'c', 'd', 'e'};
    std::array<char, system_details::CACHE_LINE_SIZE + 10> big_data_one{};

57 58
    auto big_pointer_one = stack.push<decltype(big_data_one)>(big_data_one);
    auto small_pointer_one = stack.push<decltype(small_data_one)>(small_data_one);
59 60 61 62 63 64 65 66

    REQUIRE(reinterpret_cast<std::uintptr_t>(big_pointer_one) % system_details::CACHE_LINE_SIZE == 0);
    REQUIRE(reinterpret_cast<std::uintptr_t>(small_pointer_one) % system_details::CACHE_LINE_SIZE == 0);
  }

  SECTION("stack correctly stores and retrieves objects") {
    std::array<char, 5> data_one{'a', 'b', 'c', 'd', 'e'};

67 68 69
    auto *push_one = stack.push<decltype(data_one)>(data_one);
    stack.pop<std::array<char, 5>>();
    auto *push_two = stack.push<decltype(data_one)>(data_one);
70

71
    REQUIRE(push_one == push_two);
72 73 74 75 76 77 78
  }

  SECTION("stack can push and pop multiple times with correct alignment") {
    std::array<char, 5> small_data_one{'a', 'b', 'c', 'd', 'e'};
    std::array<char, 64> small_data_two{};
    std::array<char, 1> small_data_three{'A'};

79 80 81 82 83 84 85
    auto pointer_one = stack.push<decltype(small_data_one)>(small_data_one);
    auto pointer_two = stack.push<decltype(small_data_two)>(small_data_two);
    auto pointer_three = stack.push<decltype(small_data_three)>(small_data_three);
    stack.pop<decltype(small_data_three)>();
    stack.pop<decltype(small_data_two)>();
    auto pointer_four = stack.push<decltype(small_data_two)>(small_data_two);
    auto pointer_five = stack.push<decltype(small_data_three)>(small_data_three);
86 87 88 89 90 91 92 93 94 95

    REQUIRE(reinterpret_cast<std::uintptr_t>(pointer_one) % system_details::CACHE_LINE_SIZE == 0);
    REQUIRE(reinterpret_cast<std::uintptr_t>(pointer_two) % system_details::CACHE_LINE_SIZE == 0);
    REQUIRE(reinterpret_cast<std::uintptr_t>(pointer_three) % system_details::CACHE_LINE_SIZE == 0);
    REQUIRE(reinterpret_cast<std::uintptr_t>(pointer_four) % system_details::CACHE_LINE_SIZE == 0);
    REQUIRE(reinterpret_cast<std::uintptr_t>(pointer_five) % system_details::CACHE_LINE_SIZE == 0);

    REQUIRE(pointer_four == pointer_two);
    REQUIRE(pointer_five == pointer_three);
  }
96 97
}

98