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