Home | History | Annotate | Download | only in streams
      1 // Copyright 2015 The Chromium OS Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <brillo/streams/memory_containers.h>
      6 
      7 #include <limits>
      8 #include <memory>
      9 
     10 #include <brillo/streams/mock_stream.h>
     11 #include <brillo/streams/stream_errors.h>
     12 #include <gmock/gmock.h>
     13 #include <gtest/gtest.h>
     14 
     15 using testing::DoAll;
     16 using testing::Invoke;
     17 using testing::InSequence;
     18 using testing::Return;
     19 using testing::WithArgs;
     20 using testing::_;
     21 
     22 namespace brillo {
     23 
     24 namespace {
     25 class MockContiguousBuffer : public data_container::ContiguousBufferBase {
     26  public:
     27   MockContiguousBuffer() = default;
     28 
     29   MOCK_METHOD2(Resize, bool(size_t, ErrorPtr*));
     30   MOCK_CONST_METHOD0(GetSize, size_t());
     31   MOCK_CONST_METHOD0(IsReadOnly, bool());
     32 
     33   MOCK_CONST_METHOD2(GetReadOnlyBuffer, const void*(size_t, ErrorPtr*));
     34   MOCK_METHOD2(GetBuffer, void*(size_t, ErrorPtr*));
     35 
     36   MOCK_CONST_METHOD3(CopyMemoryBlock, void(void*, const void*, size_t));
     37 
     38  private:
     39   DISALLOW_COPY_AND_ASSIGN(MockContiguousBuffer);
     40 };
     41 }  // anonymous namespace
     42 
     43 class MemoryContainerTest : public testing::Test {
     44  public:
     45   inline static void* IntToPtr(int addr) {
     46     return reinterpret_cast<void*>(addr);
     47   }
     48 
     49   inline static const void* IntToConstPtr(int addr) {
     50     return reinterpret_cast<const void*>(addr);
     51   }
     52 
     53   // Dummy buffer pointer values used as external data source/destination for
     54   // read/write operations.
     55   void* const test_read_buffer_ = IntToPtr(12345);
     56   const void* const test_write_buffer_ = IntToConstPtr(67890);
     57 
     58   // Dummy buffer pointer values used for internal buffer owned by the
     59   // memory buffer container class.
     60   const void* const const_buffer_ = IntToConstPtr(123);
     61   void* const buffer_ = IntToPtr(456);
     62 
     63   MockContiguousBuffer container_;
     64 };
     65 
     66 TEST_F(MemoryContainerTest, Read_WithinBuffer) {
     67   {
     68     InSequence s;
     69     EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
     70     EXPECT_CALL(container_, GetReadOnlyBuffer(10, _))
     71       .WillOnce(Return(const_buffer_));
     72     EXPECT_CALL(container_,
     73                 CopyMemoryBlock(test_read_buffer_, const_buffer_, 50)).Times(1);
     74   }
     75   size_t read = 0;
     76   ErrorPtr error;
     77   EXPECT_TRUE(container_.Read(test_read_buffer_, 50, 10, &read, &error));
     78   EXPECT_EQ(50, read);
     79   EXPECT_EQ(nullptr, error.get());
     80 }
     81 
     82 TEST_F(MemoryContainerTest, Read_PastEndOfBuffer) {
     83   {
     84     InSequence s;
     85     EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
     86     EXPECT_CALL(container_, GetReadOnlyBuffer(80, _))
     87       .WillOnce(Return(const_buffer_));
     88     EXPECT_CALL(container_,
     89                 CopyMemoryBlock(test_read_buffer_, const_buffer_, 20)).Times(1);
     90   }
     91   size_t read = 0;
     92   EXPECT_TRUE(container_.Read(test_read_buffer_, 50, 80, &read, nullptr));
     93   EXPECT_EQ(20, read);
     94 }
     95 
     96 TEST_F(MemoryContainerTest, Read_OutsideBuffer) {
     97   EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
     98   size_t read = 0;
     99   EXPECT_TRUE(container_.Read(test_read_buffer_, 50, 100, &read, nullptr));
    100   EXPECT_EQ(0, read);
    101 }
    102 
    103 TEST_F(MemoryContainerTest, Read_Error) {
    104   auto OnReadError = [](ErrorPtr* error) {
    105     Error::AddTo(error, FROM_HERE, "domain", "read_error", "read error");
    106   };
    107 
    108   {
    109     InSequence s;
    110     EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
    111     EXPECT_CALL(container_, GetReadOnlyBuffer(0, _))
    112       .WillOnce(DoAll(WithArgs<1>(Invoke(OnReadError)), Return(nullptr)));
    113   }
    114   size_t read = 0;
    115   ErrorPtr error;
    116   EXPECT_FALSE(container_.Read(test_read_buffer_, 10, 0, &read, &error));
    117   EXPECT_EQ(0, read);
    118   EXPECT_NE(nullptr, error.get());
    119   EXPECT_EQ("domain", error->GetDomain());
    120   EXPECT_EQ("read_error", error->GetCode());
    121   EXPECT_EQ("read error", error->GetMessage());
    122 }
    123 
    124 TEST_F(MemoryContainerTest, Write_WithinBuffer) {
    125   {
    126     InSequence s;
    127     EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
    128     EXPECT_CALL(container_, GetBuffer(10, _))
    129       .WillOnce(Return(buffer_));
    130     EXPECT_CALL(container_,
    131                 CopyMemoryBlock(buffer_, test_write_buffer_, 50)).Times(1);
    132   }
    133   size_t written = 0;
    134   ErrorPtr error;
    135   EXPECT_TRUE(container_.Write(test_write_buffer_, 50, 10, &written, &error));
    136   EXPECT_EQ(50, written);
    137   EXPECT_EQ(nullptr, error.get());
    138 }
    139 
    140 TEST_F(MemoryContainerTest, Write_PastEndOfBuffer) {
    141   {
    142     InSequence s;
    143     EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
    144     EXPECT_CALL(container_, Resize(130, _)).WillOnce(Return(true));
    145     EXPECT_CALL(container_, GetBuffer(80, _))
    146       .WillOnce(Return(buffer_));
    147     EXPECT_CALL(container_,
    148                 CopyMemoryBlock(buffer_, test_write_buffer_, 50)).Times(1);
    149   }
    150   size_t written = 0;
    151   EXPECT_TRUE(container_.Write(test_write_buffer_, 50, 80, &written, nullptr));
    152   EXPECT_EQ(50, written);
    153 }
    154 
    155 TEST_F(MemoryContainerTest, Write_OutsideBuffer) {
    156   {
    157     InSequence s;
    158     EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
    159     EXPECT_CALL(container_, Resize(160, _)).WillOnce(Return(true));
    160     EXPECT_CALL(container_, GetBuffer(110, _))
    161       .WillOnce(Return(buffer_));
    162     EXPECT_CALL(container_,
    163                 CopyMemoryBlock(buffer_, test_write_buffer_, 50)).Times(1);
    164   }
    165   size_t written = 0;
    166   EXPECT_TRUE(container_.Write(test_write_buffer_, 50, 110, &written, nullptr));
    167   EXPECT_EQ(50, written);
    168 }
    169 
    170 TEST_F(MemoryContainerTest, Write_Error_Resize) {
    171   auto OnWriteError = [](ErrorPtr* error) {
    172     Error::AddTo(error, FROM_HERE, "domain", "write_error", "resize error");
    173   };
    174 
    175   {
    176     InSequence s;
    177     EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
    178     EXPECT_CALL(container_, Resize(160, _))
    179       .WillOnce(DoAll(WithArgs<1>(Invoke(OnWriteError)), Return(false)));
    180   }
    181   size_t written = 0;
    182   ErrorPtr error;
    183   EXPECT_FALSE(container_.Write(test_write_buffer_, 50, 110, &written, &error));
    184   EXPECT_EQ(0, written);
    185   EXPECT_NE(nullptr, error.get());
    186   EXPECT_EQ("domain", error->GetDomain());
    187   EXPECT_EQ("write_error", error->GetCode());
    188   EXPECT_EQ("resize error", error->GetMessage());
    189 }
    190 
    191 TEST_F(MemoryContainerTest, Write_Error) {
    192   auto OnWriteError = [](ErrorPtr* error) {
    193     Error::AddTo(error, FROM_HERE, "domain", "write_error", "write error");
    194   };
    195 
    196   {
    197     InSequence s;
    198     EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
    199     EXPECT_CALL(container_, Resize(160, _)).WillOnce(Return(true));
    200     EXPECT_CALL(container_, GetBuffer(110, _))
    201       .WillOnce(DoAll(WithArgs<1>(Invoke(OnWriteError)), Return(nullptr)));
    202   }
    203   size_t written = 0;
    204   ErrorPtr error;
    205   EXPECT_FALSE(container_.Write(test_write_buffer_, 50, 110, &written, &error));
    206   EXPECT_EQ(0, written);
    207   EXPECT_NE(nullptr, error.get());
    208   EXPECT_EQ("domain", error->GetDomain());
    209   EXPECT_EQ("write_error", error->GetCode());
    210   EXPECT_EQ("write error", error->GetMessage());
    211 }
    212 
    213 }  // namespace brillo
    214 
    215