data_structures_test.cpp 4.46 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <catch.hpp>

#include <pls/internal/base/system_details.h>

#include <pls/internal/data_structures/aligned_stack.h>
#include <pls/internal/data_structures/deque.h>

#include <vector>
#include <mutex>

using namespace pls::internal::data_structures;
using namespace pls::internal::base;
using namespace std;

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
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<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'};

    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<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{};

    auto big_pointer_one = stack.push(big_data_one);
    auto small_pointer_one = stack.push(small_data_one);

    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'};

    stack.push(data_one);
    auto retrieved_data = stack.pop<std::array<char, 5>>();

    REQUIRE(retrieved_data == std::array<char, 5>{'a', 'b', 'c', 'd', 'e'});
  }

  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'};

    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<typeof(small_data_three)>();
    stack.pop<typeof(small_data_two)>();
    auto pointer_four = stack.push(small_data_two);
    auto pointer_five = stack.push(small_data_three);

    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);
  }
76 77
}

78 79
TEST_CASE("deque stores objects correctly", "[internal/data_structures/deque.h]") {
  class my_item : public deque_item {
80

81
  };
82

83 84
  deque<my_item> deque;
  my_item one, two, three;
85

86 87 88 89
  SECTION("add and remove items form the tail") {
    deque.push_tail(&one);
    deque.push_tail(&two);
    deque.push_tail(&three);
90

91 92 93 94
    REQUIRE(deque.pop_tail() == &three);
    REQUIRE(deque.pop_tail() == &two);
    REQUIRE(deque.pop_tail() == &one);
  }
95

96 97 98
  SECTION("handles getting empty by popping the tail correctly") {
    deque.push_tail(&one);
    REQUIRE(deque.pop_tail() == &one);
99

100 101 102
    deque.push_tail(&two);
    REQUIRE(deque.pop_tail() == &two);
  }
103

104 105 106 107
  SECTION("remove items form the head") {
    deque.push_tail(&one);
    deque.push_tail(&two);
    deque.push_tail(&three);
108

109 110 111 112
    REQUIRE(deque.pop_head() == &one);
    REQUIRE(deque.pop_head() == &two);
    REQUIRE(deque.pop_head() == &three);
  }
113

114 115 116
  SECTION("handles getting empty by popping the head correctly") {
    deque.push_tail(&one);
    REQUIRE(deque.pop_head() == &one);
117

118 119 120
    deque.push_tail(&two);
    REQUIRE(deque.pop_head() == &two);
  }
121

122 123 124
  SECTION("handles getting empty by popping the head and tail correctly") {
    deque.push_tail(&one);
    REQUIRE(deque.pop_tail() == &one);
125

126 127
    deque.push_tail(&two);
    REQUIRE(deque.pop_head() == &two);
128

129 130 131
    deque.push_tail(&three);
    REQUIRE(deque.pop_tail() == &three);
  }
132
}