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_stream.h>
      6 
      7 #include <algorithm>
      8 #include <limits>
      9 #include <numeric>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include <brillo/streams/stream_errors.h>
     14 #include <gmock/gmock.h>
     15 #include <gtest/gtest.h>
     16 
     17 using testing::DoAll;
     18 using testing::Return;
     19 using testing::SetArgPointee;
     20 using testing::_;
     21 
     22 namespace brillo {
     23 
     24 namespace {
     25 
     26 int ReadByte(Stream* stream, brillo::ErrorPtr* error) {
     27   uint8_t byte = 0;
     28   return stream->ReadAllBlocking(&byte, sizeof(byte), error) ? byte : -1;
     29 }
     30 
     31 class MockMemoryContainer : public data_container::DataContainerInterface {
     32  public:
     33   MockMemoryContainer() = default;
     34 
     35   MOCK_METHOD5(Read, bool(void*, size_t, size_t, size_t*, ErrorPtr*));
     36   MOCK_METHOD5(Write, bool(const void*, size_t, size_t, size_t*, ErrorPtr*));
     37   MOCK_METHOD2(Resize, bool(size_t, ErrorPtr*));
     38   MOCK_CONST_METHOD0(GetSize, size_t());
     39   MOCK_CONST_METHOD0(IsReadOnly, bool());
     40 
     41  private:
     42   DISALLOW_COPY_AND_ASSIGN(MockMemoryContainer);
     43 };
     44 
     45 }  // anonymous namespace
     46 
     47 class MemoryStreamTest : public testing::Test {
     48  public:
     49   void SetUp() override {
     50     std::unique_ptr<MockMemoryContainer> container{new MockMemoryContainer{}};
     51     stream_.reset(new MemoryStream{std::move(container), 0});
     52   }
     53 
     54   MockMemoryContainer& container_mock() {
     55     return *static_cast<MockMemoryContainer*>(stream_->container_.get());
     56   }
     57 
     58   inline static void* IntToPtr(int addr) {
     59     return reinterpret_cast<void*>(addr);
     60   }
     61 
     62   inline static const void* IntToConstPtr(int addr) {
     63     return reinterpret_cast<const void*>(addr);
     64   }
     65 
     66   std::unique_ptr<MemoryStream> stream_;
     67   // Dummy buffer pointer values to make sure that input pointer values
     68   // are delegated to the stream interface without a change.
     69   void* const test_read_buffer_ = IntToPtr(12345);
     70   const void* const test_write_buffer_ = IntToConstPtr(67890);
     71   // We limit the size of memory streams to be the maximum size of either of
     72   // size_t (on 32 bit platforms) or the size of signed 64 bit integer.
     73   const size_t kSizeMax =
     74       std::min<uint64_t>(std::numeric_limits<size_t>::max(),
     75                          std::numeric_limits<int64_t>::max());
     76 };
     77 
     78 TEST_F(MemoryStreamTest, CanRead) {
     79   EXPECT_TRUE(stream_->CanRead());
     80 }
     81 
     82 TEST_F(MemoryStreamTest, CanWrite) {
     83   EXPECT_CALL(container_mock(), IsReadOnly())
     84     .WillOnce(Return(true))
     85     .WillOnce(Return(false));
     86 
     87   EXPECT_FALSE(stream_->CanWrite());
     88   EXPECT_TRUE(stream_->CanWrite());
     89 }
     90 
     91 TEST_F(MemoryStreamTest, CanSeek) {
     92   EXPECT_TRUE(stream_->CanSeek());
     93 }
     94 
     95 TEST_F(MemoryStreamTest, GetSize) {
     96   EXPECT_CALL(container_mock(), GetSize())
     97     .WillOnce(Return(0))
     98     .WillOnce(Return(1234))
     99     .WillOnce(Return(kSizeMax));
    100 
    101   EXPECT_EQ(0, stream_->GetSize());
    102   EXPECT_EQ(1234, stream_->GetSize());
    103   EXPECT_EQ(kSizeMax, stream_->GetSize());
    104 }
    105 
    106 TEST_F(MemoryStreamTest, SetSizeBlocking) {
    107   EXPECT_CALL(container_mock(), Resize(0, _)).WillOnce(Return(true));
    108 
    109   ErrorPtr error;
    110   EXPECT_TRUE(stream_->SetSizeBlocking(0, &error));
    111   EXPECT_EQ(nullptr, error.get());
    112 
    113   EXPECT_CALL(container_mock(), Resize(kSizeMax, nullptr))
    114     .WillOnce(Return(true));
    115 
    116   EXPECT_TRUE(stream_->SetSizeBlocking(kSizeMax, nullptr));
    117 }
    118 
    119 TEST_F(MemoryStreamTest, SeekAndGetPosition) {
    120   EXPECT_EQ(0, stream_->GetPosition());
    121 
    122   EXPECT_CALL(container_mock(), GetSize()).WillRepeatedly(Return(200));
    123 
    124   ErrorPtr error;
    125   uint64_t new_pos = 0;
    126   EXPECT_TRUE(stream_->Seek(2, Stream::Whence::FROM_BEGIN, &new_pos, &error));
    127   EXPECT_EQ(nullptr, error.get());
    128   EXPECT_EQ(2, new_pos);
    129   EXPECT_EQ(2, stream_->GetPosition());
    130   EXPECT_TRUE(stream_->Seek(2, Stream::Whence::FROM_CURRENT, &new_pos, &error));
    131   EXPECT_EQ(nullptr, error.get());
    132   EXPECT_EQ(4, new_pos);
    133   EXPECT_EQ(4, stream_->GetPosition());
    134 
    135   EXPECT_TRUE(stream_->Seek(-2, Stream::Whence::FROM_END, nullptr, nullptr));
    136   EXPECT_EQ(198, stream_->GetPosition());
    137 
    138   EXPECT_CALL(container_mock(), GetSize()).WillOnce(Return(kSizeMax));
    139   EXPECT_TRUE(stream_->Seek(0, Stream::Whence::FROM_END, nullptr, nullptr));
    140   EXPECT_EQ(kSizeMax, stream_->GetPosition());
    141 }
    142 
    143 TEST_F(MemoryStreamTest, ReadNonBlocking) {
    144   size_t read = 0;
    145   bool eos = false;
    146 
    147   EXPECT_CALL(container_mock(), Read(test_read_buffer_, 10, 0, _, nullptr))
    148     .WillOnce(DoAll(SetArgPointee<3>(5), Return(true)));
    149 
    150   EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 10, &read, &eos,
    151                                        nullptr));
    152   EXPECT_EQ(5, read);
    153   EXPECT_EQ(5, stream_->GetPosition());
    154   EXPECT_FALSE(eos);
    155 
    156   EXPECT_CALL(container_mock(), Read(test_read_buffer_, 100, 5, _, nullptr))
    157     .WillOnce(DoAll(SetArgPointee<3>(100), Return(true)));
    158 
    159   EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 100, &read, &eos,
    160                                        nullptr));
    161   EXPECT_EQ(100, read);
    162   EXPECT_EQ(105, stream_->GetPosition());
    163   EXPECT_FALSE(eos);
    164 
    165   EXPECT_CALL(container_mock(), Read(test_read_buffer_, 10, 105, _, nullptr))
    166     .WillOnce(DoAll(SetArgPointee<3>(0), Return(true)));
    167 
    168   EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 10, &read, &eos,
    169                                        nullptr));
    170   EXPECT_EQ(0, read);
    171   EXPECT_EQ(105, stream_->GetPosition());
    172   EXPECT_TRUE(eos);
    173 }
    174 
    175 TEST_F(MemoryStreamTest, WriteNonBlocking) {
    176   size_t written = 0;
    177 
    178   EXPECT_CALL(container_mock(), Write(test_write_buffer_, 10, 0, _, nullptr))
    179     .WillOnce(DoAll(SetArgPointee<3>(5), Return(true)));
    180 
    181   EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 10, &written,
    182                                         nullptr));
    183   EXPECT_EQ(5, written);
    184   EXPECT_EQ(5, stream_->GetPosition());
    185 
    186   EXPECT_CALL(container_mock(), Write(test_write_buffer_, 100, 5, _, nullptr))
    187     .WillOnce(DoAll(SetArgPointee<3>(100), Return(true)));
    188 
    189   EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 100, &written,
    190                                         nullptr));
    191   EXPECT_EQ(100, written);
    192   EXPECT_EQ(105, stream_->GetPosition());
    193 
    194   EXPECT_CALL(container_mock(), Write(test_write_buffer_, 10, 105, _, nullptr))
    195     .WillOnce(DoAll(SetArgPointee<3>(10), Return(true)));
    196 
    197   EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 10, &written,
    198                                         nullptr));
    199   EXPECT_EQ(115, stream_->GetPosition());
    200 }
    201 
    202 //////////////////////////////////////////////////////////////////////////////
    203 // Factory method tests.
    204 TEST(MemoryStream, OpenBinary) {
    205   char buffer[] = {1, 2, 3};
    206   StreamPtr stream = MemoryStream::OpenRef(buffer, sizeof(buffer), nullptr);
    207   buffer[0] = 5;
    208   EXPECT_EQ(3, stream->GetSize());
    209   EXPECT_EQ(5, ReadByte(stream.get(), nullptr));
    210   EXPECT_EQ(2, ReadByte(stream.get(), nullptr));
    211   EXPECT_EQ(3, ReadByte(stream.get(), nullptr));
    212   brillo::ErrorPtr error;
    213   EXPECT_EQ(-1, ReadByte(stream.get(), &error));
    214   EXPECT_EQ(errors::stream::kPartialData, error->GetCode());
    215   EXPECT_EQ("Reading past the end of stream", error->GetMessage());
    216 }
    217 
    218 TEST(MemoryStream, OpenBinaryCopy) {
    219   char buffer[] = {1, 2, 3};
    220   StreamPtr stream = MemoryStream::OpenCopyOf(buffer, sizeof(buffer), nullptr);
    221   buffer[0] = 5;
    222   EXPECT_EQ(3, stream->GetSize());
    223   EXPECT_EQ(1, ReadByte(stream.get(), nullptr));
    224   EXPECT_EQ(2, ReadByte(stream.get(), nullptr));
    225   EXPECT_EQ(3, ReadByte(stream.get(), nullptr));
    226   brillo::ErrorPtr error;
    227   EXPECT_EQ(-1, ReadByte(stream.get(), &error));
    228   EXPECT_EQ(errors::stream::kPartialData, error->GetCode());
    229   EXPECT_EQ("Reading past the end of stream", error->GetMessage());
    230 }
    231 
    232 TEST(MemoryStream, OpenString) {
    233   std::string str("abcd");
    234   StreamPtr stream = MemoryStream::OpenRef(str, nullptr);
    235   str[0] = 'A';
    236   EXPECT_EQ(4, stream->GetSize());
    237   EXPECT_EQ('A', ReadByte(stream.get(), nullptr));
    238   EXPECT_EQ('b', ReadByte(stream.get(), nullptr));
    239   EXPECT_EQ('c', ReadByte(stream.get(), nullptr));
    240   EXPECT_EQ('d', ReadByte(stream.get(), nullptr));
    241   EXPECT_EQ(-1, ReadByte(stream.get(), nullptr));
    242 }
    243 
    244 TEST(MemoryStream, OpenStringCopy) {
    245   std::string str("abcd");
    246   StreamPtr stream = MemoryStream::OpenCopyOf(str, nullptr);
    247   str[0] = 'A';
    248   EXPECT_EQ(4, stream->GetSize());
    249   EXPECT_EQ('a', ReadByte(stream.get(), nullptr));
    250   EXPECT_EQ('b', ReadByte(stream.get(), nullptr));
    251   EXPECT_EQ('c', ReadByte(stream.get(), nullptr));
    252   EXPECT_EQ('d', ReadByte(stream.get(), nullptr));
    253   EXPECT_EQ(-1, ReadByte(stream.get(), nullptr));
    254 }
    255 
    256 TEST(MemoryStream, OpenCharBuf) {
    257   char str[] = "abcd";
    258   StreamPtr stream = MemoryStream::OpenRef(str, nullptr);
    259   str[0] = 'A';
    260   EXPECT_EQ(4, stream->GetSize());
    261   EXPECT_EQ('A', ReadByte(stream.get(), nullptr));
    262   EXPECT_EQ('b', ReadByte(stream.get(), nullptr));
    263   EXPECT_EQ('c', ReadByte(stream.get(), nullptr));
    264   EXPECT_EQ('d', ReadByte(stream.get(), nullptr));
    265   EXPECT_EQ(-1, ReadByte(stream.get(), nullptr));
    266 }
    267 
    268 TEST(MemoryStream, OpenCharBufCopy) {
    269   char str[] = "abcd";
    270   StreamPtr stream = MemoryStream::OpenCopyOf(str, nullptr);
    271   str[0] = 'A';
    272   EXPECT_EQ(4, stream->GetSize());
    273   EXPECT_EQ('a', ReadByte(stream.get(), nullptr));
    274   EXPECT_EQ('b', ReadByte(stream.get(), nullptr));
    275   EXPECT_EQ('c', ReadByte(stream.get(), nullptr));
    276   EXPECT_EQ('d', ReadByte(stream.get(), nullptr));
    277   EXPECT_EQ(-1, ReadByte(stream.get(), nullptr));
    278 }
    279 
    280 TEST(MemoryStream, OpenVector) {
    281   std::vector<char> data = {'a', 'b', 'c', 'd'};
    282   StreamPtr stream = MemoryStream::OpenRef(data, nullptr);
    283   data[0] = 'A';
    284   EXPECT_EQ(4, stream->GetSize());
    285   EXPECT_EQ(0, stream->GetPosition());
    286   EXPECT_EQ(4, stream->GetRemainingSize());
    287   EXPECT_EQ('A', ReadByte(stream.get(), nullptr));
    288   EXPECT_EQ('b', ReadByte(stream.get(), nullptr));
    289   EXPECT_EQ('c', ReadByte(stream.get(), nullptr));
    290   EXPECT_EQ('d', ReadByte(stream.get(), nullptr));
    291   EXPECT_EQ(4, stream->GetPosition());
    292   EXPECT_EQ(4, stream->GetSize());
    293   EXPECT_EQ(0, stream->GetRemainingSize());
    294 }
    295 
    296 TEST(MemoryStream, OpenVectorCopy) {
    297   std::vector<uint8_t> data = {'a', 'b', 'c', 'd'};
    298   StreamPtr stream = MemoryStream::OpenCopyOf(data, nullptr);
    299   data[0] = 'A';
    300   EXPECT_EQ(4, stream->GetSize());
    301   EXPECT_EQ(0, stream->GetPosition());
    302   EXPECT_EQ(4, stream->GetRemainingSize());
    303   EXPECT_EQ('a', ReadByte(stream.get(), nullptr));
    304   EXPECT_EQ('b', ReadByte(stream.get(), nullptr));
    305   EXPECT_EQ('c', ReadByte(stream.get(), nullptr));
    306   EXPECT_EQ('d', ReadByte(stream.get(), nullptr));
    307   EXPECT_EQ(4, stream->GetPosition());
    308   EXPECT_EQ(4, stream->GetSize());
    309   EXPECT_EQ(0, stream->GetRemainingSize());
    310 }
    311 
    312 TEST(MemoryStream, CreateVector) {
    313   std::vector<uint8_t> buffer;
    314   StreamPtr stream = MemoryStream::CreateRef(&buffer, nullptr);
    315   EXPECT_TRUE(buffer.empty());
    316   EXPECT_EQ(0, stream->GetPosition());
    317   EXPECT_EQ(0, stream->GetSize());
    318   EXPECT_TRUE(stream->CloseBlocking(nullptr));
    319 
    320   buffer.resize(5);
    321   std::iota(buffer.begin(), buffer.end(), 0);
    322   stream = MemoryStream::CreateRef(&buffer, nullptr);
    323   EXPECT_FALSE(buffer.empty());
    324   EXPECT_EQ(0, stream->GetPosition());
    325   EXPECT_EQ(5, stream->GetSize());
    326   EXPECT_TRUE(stream->CloseBlocking(nullptr));
    327 
    328   stream = MemoryStream::CreateRefForAppend(&buffer, nullptr);
    329   EXPECT_FALSE(buffer.empty());
    330   EXPECT_EQ(5, stream->GetPosition());
    331   EXPECT_EQ(5, stream->GetSize());
    332   EXPECT_TRUE(stream->WriteAllBlocking("abcde", 5, nullptr));
    333   EXPECT_FALSE(buffer.empty());
    334   EXPECT_EQ(10, stream->GetPosition());
    335   EXPECT_EQ(10, stream->GetSize());
    336   EXPECT_TRUE(stream->SetPosition(0, nullptr));
    337   EXPECT_EQ(0, stream->GetPosition());
    338   EXPECT_EQ(10, stream->GetSize());
    339   EXPECT_TRUE(stream->CloseBlocking(nullptr));
    340 
    341   EXPECT_EQ(10, buffer.size());
    342   EXPECT_EQ((std::vector<uint8_t>{0, 1, 2, 3, 4, 'a', 'b', 'c', 'd', 'e'}),
    343             buffer);
    344 
    345   stream = MemoryStream::OpenRef(buffer, nullptr);
    346   EXPECT_FALSE(buffer.empty());
    347   EXPECT_EQ(0, stream->GetPosition());
    348   EXPECT_EQ(10, stream->GetSize());
    349 }
    350 
    351 TEST(MemoryStream, CreateString) {
    352   std::string buffer;
    353   StreamPtr stream = MemoryStream::CreateRef(&buffer, nullptr);
    354   EXPECT_TRUE(buffer.empty());
    355   EXPECT_EQ(0, stream->GetPosition());
    356   EXPECT_EQ(0, stream->GetSize());
    357   EXPECT_TRUE(stream->CloseBlocking(nullptr));
    358 
    359   buffer = "abc";
    360   stream = MemoryStream::CreateRef(&buffer, nullptr);
    361   EXPECT_FALSE(buffer.empty());
    362   EXPECT_EQ(0, stream->GetPosition());
    363   EXPECT_EQ(3, stream->GetSize());
    364   EXPECT_TRUE(stream->CloseBlocking(nullptr));
    365 
    366   stream = MemoryStream::CreateRefForAppend(&buffer, nullptr);
    367   EXPECT_FALSE(buffer.empty());
    368   EXPECT_EQ(3, stream->GetPosition());
    369   EXPECT_EQ(3, stream->GetSize());
    370   EXPECT_TRUE(stream->WriteAllBlocking("d_1234", 6, nullptr));
    371   EXPECT_FALSE(buffer.empty());
    372   EXPECT_EQ(9, stream->GetPosition());
    373   EXPECT_EQ(9, stream->GetSize());
    374   EXPECT_TRUE(stream->SetPosition(0, nullptr));
    375   EXPECT_EQ(0, stream->GetPosition());
    376   EXPECT_EQ(9, stream->GetSize());
    377   EXPECT_TRUE(stream->CloseBlocking(nullptr));
    378   EXPECT_EQ(9, buffer.size());
    379   EXPECT_EQ("abcd_1234", buffer);
    380 }
    381 
    382 }  // namespace brillo
    383