1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <memory>
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <string>
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <thread>
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <utility>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <gtest/gtest.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/rpc/message_buffer.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace rpc {
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ThreadLocalBufferTest {
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Returns the unique address of the thread-local buffer. Used to test the
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // correct behavior of the type-based thread local storage slot mapping
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // mechanism.
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  template <typename Slot>
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static std::uintptr_t GetSlotAddress() {
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return reinterpret_cast<std::uintptr_t>(&MessageBuffer<Slot>::buffer_);
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Returns the raw value of the thread local buffer. Used to test the behavior
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // of backing buffer initialization.
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  template <typename Slot>
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static std::uintptr_t GetSlotValue() {
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return reinterpret_cast<std::uintptr_t>(MessageBuffer<Slot>::buffer_);
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace rpc
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing namespace android::pdx::rpc;
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace {
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct TypeTagA;
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct TypeTagB;
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconstexpr std::size_t kSendBufferIndex = 0;
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconstexpr std::size_t kReceiveBufferIndex = 1;
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing SendSlotA = ThreadLocalSlot<TypeTagA, kSendBufferIndex>;
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing SendSlotB = ThreadLocalSlot<TypeTagB, kSendBufferIndex>;
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing ReceiveSlotA = ThreadLocalSlot<TypeTagA, kReceiveBufferIndex>;
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing ReceiveSlotB = ThreadLocalSlot<TypeTagB, kReceiveBufferIndex>;
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Tests that index and type-based thread-local slot addressing works by
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// checking that the slot address is the same when the same index/type
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// combination is used and different when different combinations are used.
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST(ThreadLocalBufferTest, TypeSlots) {
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto id1 = ThreadLocalBufferTest::GetSlotAddress<SendSlotA>();
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto id2 = ThreadLocalBufferTest::GetSlotAddress<ReceiveSlotA>();
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto id3 = ThreadLocalBufferTest::GetSlotAddress<SendSlotB>();
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto id4 = ThreadLocalBufferTest::GetSlotAddress<ReceiveSlotB>();
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(id1, id2);
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(id3, id4);
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(id1, id3);
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(id2, id4);
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto id1_alias = ThreadLocalBufferTest::GetSlotAddress<SendSlotA>();
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto id2_alias = ThreadLocalBufferTest::GetSlotAddress<ReceiveSlotA>();
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto id3_alias = ThreadLocalBufferTest::GetSlotAddress<SendSlotB>();
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto id4_alias = ThreadLocalBufferTest::GetSlotAddress<ReceiveSlotB>();
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(id1, id1_alias);
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(id2, id2_alias);
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(id3, id3_alias);
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(id4, id4_alias);
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Tests that different threads get different buffers for the same slot address.
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST(ThreadLocalBufferTest, ThreadSlots) {
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto id1 = ThreadLocalBufferTest::GetSlotAddress<SendBuffer>();
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::uintptr_t id2 = 0U;
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::thread thread([&id2]() mutable {
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    id2 = ThreadLocalBufferTest::GetSlotAddress<SendBuffer>();
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  });
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  thread.join();
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(0U, id1);
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(0U, id2);
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(id1, id2);
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Tests that thread-local buffers are allocated at the first buffer request.
9386a8d3402474bd3cdf7b42b61f51f2423748fc11Alex VakulenkoTEST(ThreadLocalBufferTest, InitialValue) {
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  struct TypeTagX;
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using SendSlotX = ThreadLocalSlot<TypeTagX, kSendBufferIndex>;
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto value1 = ThreadLocalBufferTest::GetSlotValue<SendSlotX>();
9886a8d3402474bd3cdf7b42b61f51f2423748fc11Alex Vakulenko  MessageBuffer<SendSlotX>::GetBuffer();
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto value2 = ThreadLocalBufferTest::GetSlotValue<SendSlotX>();
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(0U, value1);
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(0U, value2);
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Tests that the underlying buffers are the same for a given index/type pair
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// and different across index/type combinations.
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST(ThreadLocalBufferTest, BackingBuffer) {
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto& buffer1 = MessageBuffer<SendSlotA>::GetBuffer();
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto& buffer2 = MessageBuffer<SendSlotA>::GetBuffer();
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto& buffer3 = MessageBuffer<SendSlotB>::GetBuffer();
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto& buffer4 = MessageBuffer<SendSlotB>::GetBuffer();
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(buffer1.data(), buffer2.data());
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(buffer3.data(), buffer4.data());
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(buffer1.data(), buffer3.data());
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(buffer2.data(), buffer4.data());
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
118