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_containers.h> 6 7 #include <limits> 8 #include <memory> 9 10 #include <brillo/streams/mock_stream.h> 11 #include <brillo/streams/stream_errors.h> 12 #include <gmock/gmock.h> 13 #include <gtest/gtest.h> 14 15 using testing::DoAll; 16 using testing::Invoke; 17 using testing::InSequence; 18 using testing::Return; 19 using testing::WithArgs; 20 using testing::_; 21 22 namespace brillo { 23 24 namespace { 25 class MockContiguousBuffer : public data_container::ContiguousBufferBase { 26 public: 27 MockContiguousBuffer() = default; 28 29 MOCK_METHOD2(Resize, bool(size_t, ErrorPtr*)); 30 MOCK_CONST_METHOD0(GetSize, size_t()); 31 MOCK_CONST_METHOD0(IsReadOnly, bool()); 32 33 MOCK_CONST_METHOD2(GetReadOnlyBuffer, const void*(size_t, ErrorPtr*)); 34 MOCK_METHOD2(GetBuffer, void*(size_t, ErrorPtr*)); 35 36 MOCK_CONST_METHOD3(CopyMemoryBlock, void(void*, const void*, size_t)); 37 38 private: 39 DISALLOW_COPY_AND_ASSIGN(MockContiguousBuffer); 40 }; 41 } // anonymous namespace 42 43 class MemoryContainerTest : public testing::Test { 44 public: 45 inline static void* IntToPtr(int addr) { 46 return reinterpret_cast<void*>(addr); 47 } 48 49 inline static const void* IntToConstPtr(int addr) { 50 return reinterpret_cast<const void*>(addr); 51 } 52 53 // Dummy buffer pointer values used as external data source/destination for 54 // read/write operations. 55 void* const test_read_buffer_ = IntToPtr(12345); 56 const void* const test_write_buffer_ = IntToConstPtr(67890); 57 58 // Dummy buffer pointer values used for internal buffer owned by the 59 // memory buffer container class. 60 const void* const const_buffer_ = IntToConstPtr(123); 61 void* const buffer_ = IntToPtr(456); 62 63 MockContiguousBuffer container_; 64 }; 65 66 TEST_F(MemoryContainerTest, Read_WithinBuffer) { 67 { 68 InSequence s; 69 EXPECT_CALL(container_, GetSize()).WillOnce(Return(100)); 70 EXPECT_CALL(container_, GetReadOnlyBuffer(10, _)) 71 .WillOnce(Return(const_buffer_)); 72 EXPECT_CALL(container_, 73 CopyMemoryBlock(test_read_buffer_, const_buffer_, 50)).Times(1); 74 } 75 size_t read = 0; 76 ErrorPtr error; 77 EXPECT_TRUE(container_.Read(test_read_buffer_, 50, 10, &read, &error)); 78 EXPECT_EQ(50, read); 79 EXPECT_EQ(nullptr, error.get()); 80 } 81 82 TEST_F(MemoryContainerTest, Read_PastEndOfBuffer) { 83 { 84 InSequence s; 85 EXPECT_CALL(container_, GetSize()).WillOnce(Return(100)); 86 EXPECT_CALL(container_, GetReadOnlyBuffer(80, _)) 87 .WillOnce(Return(const_buffer_)); 88 EXPECT_CALL(container_, 89 CopyMemoryBlock(test_read_buffer_, const_buffer_, 20)).Times(1); 90 } 91 size_t read = 0; 92 EXPECT_TRUE(container_.Read(test_read_buffer_, 50, 80, &read, nullptr)); 93 EXPECT_EQ(20, read); 94 } 95 96 TEST_F(MemoryContainerTest, Read_OutsideBuffer) { 97 EXPECT_CALL(container_, GetSize()).WillOnce(Return(100)); 98 size_t read = 0; 99 EXPECT_TRUE(container_.Read(test_read_buffer_, 50, 100, &read, nullptr)); 100 EXPECT_EQ(0, read); 101 } 102 103 TEST_F(MemoryContainerTest, Read_Error) { 104 auto OnReadError = [](ErrorPtr* error) { 105 Error::AddTo(error, FROM_HERE, "domain", "read_error", "read error"); 106 }; 107 108 { 109 InSequence s; 110 EXPECT_CALL(container_, GetSize()).WillOnce(Return(100)); 111 EXPECT_CALL(container_, GetReadOnlyBuffer(0, _)) 112 .WillOnce(DoAll(WithArgs<1>(Invoke(OnReadError)), Return(nullptr))); 113 } 114 size_t read = 0; 115 ErrorPtr error; 116 EXPECT_FALSE(container_.Read(test_read_buffer_, 10, 0, &read, &error)); 117 EXPECT_EQ(0, read); 118 EXPECT_NE(nullptr, error.get()); 119 EXPECT_EQ("domain", error->GetDomain()); 120 EXPECT_EQ("read_error", error->GetCode()); 121 EXPECT_EQ("read error", error->GetMessage()); 122 } 123 124 TEST_F(MemoryContainerTest, Write_WithinBuffer) { 125 { 126 InSequence s; 127 EXPECT_CALL(container_, GetSize()).WillOnce(Return(100)); 128 EXPECT_CALL(container_, GetBuffer(10, _)) 129 .WillOnce(Return(buffer_)); 130 EXPECT_CALL(container_, 131 CopyMemoryBlock(buffer_, test_write_buffer_, 50)).Times(1); 132 } 133 size_t written = 0; 134 ErrorPtr error; 135 EXPECT_TRUE(container_.Write(test_write_buffer_, 50, 10, &written, &error)); 136 EXPECT_EQ(50, written); 137 EXPECT_EQ(nullptr, error.get()); 138 } 139 140 TEST_F(MemoryContainerTest, Write_PastEndOfBuffer) { 141 { 142 InSequence s; 143 EXPECT_CALL(container_, GetSize()).WillOnce(Return(100)); 144 EXPECT_CALL(container_, Resize(130, _)).WillOnce(Return(true)); 145 EXPECT_CALL(container_, GetBuffer(80, _)) 146 .WillOnce(Return(buffer_)); 147 EXPECT_CALL(container_, 148 CopyMemoryBlock(buffer_, test_write_buffer_, 50)).Times(1); 149 } 150 size_t written = 0; 151 EXPECT_TRUE(container_.Write(test_write_buffer_, 50, 80, &written, nullptr)); 152 EXPECT_EQ(50, written); 153 } 154 155 TEST_F(MemoryContainerTest, Write_OutsideBuffer) { 156 { 157 InSequence s; 158 EXPECT_CALL(container_, GetSize()).WillOnce(Return(100)); 159 EXPECT_CALL(container_, Resize(160, _)).WillOnce(Return(true)); 160 EXPECT_CALL(container_, GetBuffer(110, _)) 161 .WillOnce(Return(buffer_)); 162 EXPECT_CALL(container_, 163 CopyMemoryBlock(buffer_, test_write_buffer_, 50)).Times(1); 164 } 165 size_t written = 0; 166 EXPECT_TRUE(container_.Write(test_write_buffer_, 50, 110, &written, nullptr)); 167 EXPECT_EQ(50, written); 168 } 169 170 TEST_F(MemoryContainerTest, Write_Error_Resize) { 171 auto OnWriteError = [](ErrorPtr* error) { 172 Error::AddTo(error, FROM_HERE, "domain", "write_error", "resize error"); 173 }; 174 175 { 176 InSequence s; 177 EXPECT_CALL(container_, GetSize()).WillOnce(Return(100)); 178 EXPECT_CALL(container_, Resize(160, _)) 179 .WillOnce(DoAll(WithArgs<1>(Invoke(OnWriteError)), Return(false))); 180 } 181 size_t written = 0; 182 ErrorPtr error; 183 EXPECT_FALSE(container_.Write(test_write_buffer_, 50, 110, &written, &error)); 184 EXPECT_EQ(0, written); 185 EXPECT_NE(nullptr, error.get()); 186 EXPECT_EQ("domain", error->GetDomain()); 187 EXPECT_EQ("write_error", error->GetCode()); 188 EXPECT_EQ("resize error", error->GetMessage()); 189 } 190 191 TEST_F(MemoryContainerTest, Write_Error) { 192 auto OnWriteError = [](ErrorPtr* error) { 193 Error::AddTo(error, FROM_HERE, "domain", "write_error", "write error"); 194 }; 195 196 { 197 InSequence s; 198 EXPECT_CALL(container_, GetSize()).WillOnce(Return(100)); 199 EXPECT_CALL(container_, Resize(160, _)).WillOnce(Return(true)); 200 EXPECT_CALL(container_, GetBuffer(110, _)) 201 .WillOnce(DoAll(WithArgs<1>(Invoke(OnWriteError)), Return(nullptr))); 202 } 203 size_t written = 0; 204 ErrorPtr error; 205 EXPECT_FALSE(container_.Write(test_write_buffer_, 50, 110, &written, &error)); 206 EXPECT_EQ(0, written); 207 EXPECT_NE(nullptr, error.get()); 208 EXPECT_EQ("domain", error->GetDomain()); 209 EXPECT_EQ("write_error", error->GetCode()); 210 EXPECT_EQ("write error", error->GetMessage()); 211 } 212 213 } // namespace brillo 214 215