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