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 
ReadByte(Stream * stream,brillo::ErrorPtr * error)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:
SetUp()49   void SetUp() override {
50     std::unique_ptr<MockMemoryContainer> container{new MockMemoryContainer{}};
51     stream_.reset(new MemoryStream{std::move(container), 0});
52   }
53 
container_mock()54   MockMemoryContainer& container_mock() {
55     return *static_cast<MockMemoryContainer*>(stream_->container_.get());
56   }
57 
IntToPtr(int addr)58   inline static void* IntToPtr(int addr) {
59     return reinterpret_cast<void*>(addr);
60   }
61 
IntToConstPtr(int addr)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 
TEST_F(MemoryStreamTest,CanRead)78 TEST_F(MemoryStreamTest, CanRead) {
79   EXPECT_TRUE(stream_->CanRead());
80 }
81 
TEST_F(MemoryStreamTest,CanWrite)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 
TEST_F(MemoryStreamTest,CanSeek)91 TEST_F(MemoryStreamTest, CanSeek) {
92   EXPECT_TRUE(stream_->CanSeek());
93 }
94 
TEST_F(MemoryStreamTest,GetSize)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 
TEST_F(MemoryStreamTest,SetSizeBlocking)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 
TEST_F(MemoryStreamTest,SeekAndGetPosition)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 
TEST_F(MemoryStreamTest,ReadNonBlocking)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 
TEST_F(MemoryStreamTest,WriteNonBlocking)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.
TEST(MemoryStream,OpenBinary)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 
TEST(MemoryStream,OpenBinaryCopy)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 
TEST(MemoryStream,OpenString)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 
TEST(MemoryStream,OpenStringCopy)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 
TEST(MemoryStream,OpenCharBuf)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 
TEST(MemoryStream,OpenCharBufCopy)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 
TEST(MemoryStream,OpenVector)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 
TEST(MemoryStream,OpenVectorCopy)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 
TEST(MemoryStream,CreateVector)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 
TEST(MemoryStream,CreateString)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