You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
221 lines
6.8 KiB
221 lines
6.8 KiB
7 months ago
|
// Copyright 2015 The Chromium OS Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#include <brillo/streams/memory_containers.h>
|
||
|
|
||
|
#include <limits>
|
||
|
#include <memory>
|
||
|
|
||
|
#include <brillo/streams/mock_stream.h>
|
||
|
#include <brillo/streams/stream_errors.h>
|
||
|
#include <gmock/gmock.h>
|
||
|
#include <gtest/gtest.h>
|
||
|
|
||
|
using testing::DoAll;
|
||
|
using testing::Invoke;
|
||
|
using testing::InSequence;
|
||
|
using testing::Return;
|
||
|
using testing::WithArgs;
|
||
|
using testing::_;
|
||
|
|
||
|
namespace brillo {
|
||
|
|
||
|
namespace {
|
||
|
class MockContiguousBuffer : public data_container::ContiguousBufferBase {
|
||
|
public:
|
||
|
MockContiguousBuffer() = default;
|
||
|
|
||
|
MOCK_METHOD(bool, Resize, (size_t, ErrorPtr*), (override));
|
||
|
MOCK_METHOD(size_t, GetSize, (), (const, override));
|
||
|
MOCK_METHOD(bool, IsReadOnly, (), (const, override));
|
||
|
|
||
|
MOCK_METHOD(const void*,
|
||
|
GetReadOnlyBuffer,
|
||
|
(size_t, ErrorPtr*),
|
||
|
(const, override));
|
||
|
MOCK_METHOD(void*, GetBuffer, (size_t, ErrorPtr*), (override));
|
||
|
|
||
|
MOCK_METHOD(void,
|
||
|
CopyMemoryBlock,
|
||
|
(void*, const void*, size_t),
|
||
|
(const, override));
|
||
|
|
||
|
private:
|
||
|
DISALLOW_COPY_AND_ASSIGN(MockContiguousBuffer);
|
||
|
};
|
||
|
} // anonymous namespace
|
||
|
|
||
|
class MemoryContainerTest : public testing::Test {
|
||
|
public:
|
||
|
inline static void* IntToPtr(int addr) {
|
||
|
return reinterpret_cast<void*>(addr);
|
||
|
}
|
||
|
|
||
|
inline static const void* IntToConstPtr(int addr) {
|
||
|
return reinterpret_cast<const void*>(addr);
|
||
|
}
|
||
|
|
||
|
// Dummy buffer pointer values used as external data source/destination for
|
||
|
// read/write operations.
|
||
|
void* const test_read_buffer_ = IntToPtr(12345);
|
||
|
const void* const test_write_buffer_ = IntToConstPtr(67890);
|
||
|
|
||
|
// Dummy buffer pointer values used for internal buffer owned by the
|
||
|
// memory buffer container class.
|
||
|
const void* const const_buffer_ = IntToConstPtr(123);
|
||
|
void* const buffer_ = IntToPtr(456);
|
||
|
|
||
|
MockContiguousBuffer container_;
|
||
|
};
|
||
|
|
||
|
TEST_F(MemoryContainerTest, Read_WithinBuffer) {
|
||
|
{
|
||
|
InSequence s;
|
||
|
EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
|
||
|
EXPECT_CALL(container_, GetReadOnlyBuffer(10, _))
|
||
|
.WillOnce(Return(const_buffer_));
|
||
|
EXPECT_CALL(container_,
|
||
|
CopyMemoryBlock(test_read_buffer_, const_buffer_, 50)).Times(1);
|
||
|
}
|
||
|
size_t read = 0;
|
||
|
ErrorPtr error;
|
||
|
EXPECT_TRUE(container_.Read(test_read_buffer_, 50, 10, &read, &error));
|
||
|
EXPECT_EQ(50, read);
|
||
|
EXPECT_EQ(nullptr, error.get());
|
||
|
}
|
||
|
|
||
|
TEST_F(MemoryContainerTest, Read_PastEndOfBuffer) {
|
||
|
{
|
||
|
InSequence s;
|
||
|
EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
|
||
|
EXPECT_CALL(container_, GetReadOnlyBuffer(80, _))
|
||
|
.WillOnce(Return(const_buffer_));
|
||
|
EXPECT_CALL(container_,
|
||
|
CopyMemoryBlock(test_read_buffer_, const_buffer_, 20)).Times(1);
|
||
|
}
|
||
|
size_t read = 0;
|
||
|
EXPECT_TRUE(container_.Read(test_read_buffer_, 50, 80, &read, nullptr));
|
||
|
EXPECT_EQ(20, read);
|
||
|
}
|
||
|
|
||
|
TEST_F(MemoryContainerTest, Read_OutsideBuffer) {
|
||
|
EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
|
||
|
size_t read = 0;
|
||
|
EXPECT_TRUE(container_.Read(test_read_buffer_, 50, 100, &read, nullptr));
|
||
|
EXPECT_EQ(0, read);
|
||
|
}
|
||
|
|
||
|
TEST_F(MemoryContainerTest, Read_Error) {
|
||
|
auto OnReadError = [](ErrorPtr* error) {
|
||
|
Error::AddTo(error, FROM_HERE, "domain", "read_error", "read error");
|
||
|
};
|
||
|
|
||
|
{
|
||
|
InSequence s;
|
||
|
EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
|
||
|
EXPECT_CALL(container_, GetReadOnlyBuffer(0, _))
|
||
|
.WillOnce(DoAll(WithArgs<1>(Invoke(OnReadError)), Return(nullptr)));
|
||
|
}
|
||
|
size_t read = 0;
|
||
|
ErrorPtr error;
|
||
|
EXPECT_FALSE(container_.Read(test_read_buffer_, 10, 0, &read, &error));
|
||
|
EXPECT_EQ(0, read);
|
||
|
EXPECT_NE(nullptr, error.get());
|
||
|
EXPECT_EQ("domain", error->GetDomain());
|
||
|
EXPECT_EQ("read_error", error->GetCode());
|
||
|
EXPECT_EQ("read error", error->GetMessage());
|
||
|
}
|
||
|
|
||
|
TEST_F(MemoryContainerTest, Write_WithinBuffer) {
|
||
|
{
|
||
|
InSequence s;
|
||
|
EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
|
||
|
EXPECT_CALL(container_, GetBuffer(10, _))
|
||
|
.WillOnce(Return(buffer_));
|
||
|
EXPECT_CALL(container_,
|
||
|
CopyMemoryBlock(buffer_, test_write_buffer_, 50)).Times(1);
|
||
|
}
|
||
|
size_t written = 0;
|
||
|
ErrorPtr error;
|
||
|
EXPECT_TRUE(container_.Write(test_write_buffer_, 50, 10, &written, &error));
|
||
|
EXPECT_EQ(50, written);
|
||
|
EXPECT_EQ(nullptr, error.get());
|
||
|
}
|
||
|
|
||
|
TEST_F(MemoryContainerTest, Write_PastEndOfBuffer) {
|
||
|
{
|
||
|
InSequence s;
|
||
|
EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
|
||
|
EXPECT_CALL(container_, Resize(130, _)).WillOnce(Return(true));
|
||
|
EXPECT_CALL(container_, GetBuffer(80, _))
|
||
|
.WillOnce(Return(buffer_));
|
||
|
EXPECT_CALL(container_,
|
||
|
CopyMemoryBlock(buffer_, test_write_buffer_, 50)).Times(1);
|
||
|
}
|
||
|
size_t written = 0;
|
||
|
EXPECT_TRUE(container_.Write(test_write_buffer_, 50, 80, &written, nullptr));
|
||
|
EXPECT_EQ(50, written);
|
||
|
}
|
||
|
|
||
|
TEST_F(MemoryContainerTest, Write_OutsideBuffer) {
|
||
|
{
|
||
|
InSequence s;
|
||
|
EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
|
||
|
EXPECT_CALL(container_, Resize(160, _)).WillOnce(Return(true));
|
||
|
EXPECT_CALL(container_, GetBuffer(110, _))
|
||
|
.WillOnce(Return(buffer_));
|
||
|
EXPECT_CALL(container_,
|
||
|
CopyMemoryBlock(buffer_, test_write_buffer_, 50)).Times(1);
|
||
|
}
|
||
|
size_t written = 0;
|
||
|
EXPECT_TRUE(container_.Write(test_write_buffer_, 50, 110, &written, nullptr));
|
||
|
EXPECT_EQ(50, written);
|
||
|
}
|
||
|
|
||
|
TEST_F(MemoryContainerTest, Write_Error_Resize) {
|
||
|
auto OnWriteError = [](ErrorPtr* error) {
|
||
|
Error::AddTo(error, FROM_HERE, "domain", "write_error", "resize error");
|
||
|
};
|
||
|
|
||
|
{
|
||
|
InSequence s;
|
||
|
EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
|
||
|
EXPECT_CALL(container_, Resize(160, _))
|
||
|
.WillOnce(DoAll(WithArgs<1>(Invoke(OnWriteError)), Return(false)));
|
||
|
}
|
||
|
size_t written = 0;
|
||
|
ErrorPtr error;
|
||
|
EXPECT_FALSE(container_.Write(test_write_buffer_, 50, 110, &written, &error));
|
||
|
EXPECT_EQ(0, written);
|
||
|
EXPECT_NE(nullptr, error.get());
|
||
|
EXPECT_EQ("domain", error->GetDomain());
|
||
|
EXPECT_EQ("write_error", error->GetCode());
|
||
|
EXPECT_EQ("resize error", error->GetMessage());
|
||
|
}
|
||
|
|
||
|
TEST_F(MemoryContainerTest, Write_Error) {
|
||
|
auto OnWriteError = [](ErrorPtr* error) {
|
||
|
Error::AddTo(error, FROM_HERE, "domain", "write_error", "write error");
|
||
|
};
|
||
|
|
||
|
{
|
||
|
InSequence s;
|
||
|
EXPECT_CALL(container_, GetSize()).WillOnce(Return(100));
|
||
|
EXPECT_CALL(container_, Resize(160, _)).WillOnce(Return(true));
|
||
|
EXPECT_CALL(container_, GetBuffer(110, _))
|
||
|
.WillOnce(DoAll(WithArgs<1>(Invoke(OnWriteError)), Return(nullptr)));
|
||
|
}
|
||
|
size_t written = 0;
|
||
|
ErrorPtr error;
|
||
|
EXPECT_FALSE(container_.Write(test_write_buffer_, 50, 110, &written, &error));
|
||
|
EXPECT_EQ(0, written);
|
||
|
EXPECT_NE(nullptr, error.get());
|
||
|
EXPECT_EQ("domain", error->GetDomain());
|
||
|
EXPECT_EQ("write_error", error->GetCode());
|
||
|
EXPECT_EQ("write error", error->GetMessage());
|
||
|
}
|
||
|
|
||
|
} // namespace brillo
|
||
|
|