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