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