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