blob: 0464bf237d5425385ab7d748511c6deb0d708e6e [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2021 Google
#include "buffer_service.hpp"
#include "config.hpp"
#include "dbus_loop_mock.hpp"
#include "file_storage_mock.hpp"
#include "host_console_mock.hpp"
#include "log_buffer_mock.hpp"
#include <memory>
#include <string>
#include <system_error>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace
{
constexpr char firstDatagram[] = "Hello world";
// Shouldn't read more than maximum size of a datagram.
constexpr int consoleReadMaxSize = 1024;
using ::testing::_;
using ::testing::DoAll;
using ::testing::Eq;
using ::testing::InSequence;
using ::testing::Le;
using ::testing::Ref;
using ::testing::Return;
using ::testing::SetArrayArgument;
using ::testing::StrEq;
using ::testing::Test;
using ::testing::Throw;
// A helper class that owns config.
struct ConfigInTest
{
Config config;
ConfigInTest() : config() {}
};
class BufferServiceTest : public Test, public ConfigInTest, public BufferService
{
public:
// ConfigInTest::config is initialized before BufferService.
BufferServiceTest() :
BufferService(ConfigInTest::config, dbusLoopMock, hostConsoleMock,
logBufferMock, fileStorageMock)
{}
MOCK_METHOD(void, flush, (), (override));
MOCK_METHOD(void, readConsole, (), (override));
protected:
// Set hostConsole firstly read specified data and then read nothing.
void setHostConsoleOnce(const char* data, size_t len)
{
EXPECT_CALL(hostConsoleMock, read(_, Le(consoleReadMaxSize)))
.WillOnce(DoAll(SetArrayArgument<0>(data, data + len), Return(len)))
.WillOnce(Return(0));
}
DbusLoopMock dbusLoopMock;
HostConsoleMock hostConsoleMock;
LogBufferMock logBufferMock;
FileStorageMock fileStorageMock;
};
TEST_F(BufferServiceTest, FlushEmptyBuffer)
{
EXPECT_CALL(logBufferMock, empty()).WillOnce(Return(true));
EXPECT_NO_THROW(BufferService::flush());
}
TEST_F(BufferServiceTest, FlushExceptionCaught)
{
InSequence sequence;
EXPECT_CALL(logBufferMock, empty()).WillOnce(Return(false));
EXPECT_CALL(fileStorageMock, save(Ref(logBufferMock)))
.WillOnce(Throw(std::runtime_error("Mock error")));
EXPECT_NO_THROW(BufferService::flush());
}
TEST_F(BufferServiceTest, FlushOk)
{
InSequence sequence;
EXPECT_CALL(logBufferMock, empty()).WillOnce(Return(false));
EXPECT_CALL(fileStorageMock, save(Ref(logBufferMock)));
EXPECT_CALL(logBufferMock, clear());
EXPECT_NO_THROW(BufferService::flush());
}
TEST_F(BufferServiceTest, ReadConsoleExceptionCaught)
{
InSequence sequence;
// Shouldn't read more than maximum size of a datagram.
EXPECT_CALL(hostConsoleMock, read(_, Le(1024)))
.WillOnce(Throw(std::system_error(std::error_code(), "Mock error")));
EXPECT_NO_THROW(BufferService::readConsole());
}
TEST_F(BufferServiceTest, ReadConsoleOk)
{
setHostConsoleOnce(firstDatagram, strlen(firstDatagram));
EXPECT_CALL(logBufferMock,
append(StrEq(firstDatagram), Eq(strlen(firstDatagram))))
.WillOnce(Return());
EXPECT_NO_THROW(BufferService::readConsole());
}
TEST_F(BufferServiceTest, RunIoRegisterError)
{
EXPECT_CALL(hostConsoleMock, connect()).WillOnce(Return());
EXPECT_CALL(dbusLoopMock, addSignalHandler(Eq(SIGUSR1), _))
.WillOnce(Return());
EXPECT_CALL(dbusLoopMock, addSignalHandler(Eq(SIGTERM), _))
.WillOnce(Return());
EXPECT_CALL(dbusLoopMock, addIoHandler(Eq(int(hostConsoleMock)), _))
.WillOnce(Throw(std::runtime_error("Mock error")));
EXPECT_THROW(run(), std::runtime_error);
}
TEST_F(BufferServiceTest, RunSignalRegisterError)
{
EXPECT_CALL(hostConsoleMock, connect()).WillOnce(Return());
EXPECT_CALL(dbusLoopMock, addSignalHandler(Eq(SIGUSR1), _))
.WillOnce(Throw(std::runtime_error("Mock error")));
EXPECT_THROW(run(), std::runtime_error);
}
TEST_F(BufferServiceTest, RunOk)
{
ConfigInTest::config.bufFlushFull = true;
EXPECT_CALL(hostConsoleMock, connect()).WillOnce(Return());
EXPECT_CALL(dbusLoopMock, addIoHandler(Eq(int(hostConsoleMock)), _))
.WillOnce(Return());
EXPECT_CALL(dbusLoopMock, addSignalHandler(Eq(SIGTERM), _))
.WillOnce(Return());
EXPECT_CALL(logBufferMock, setFullHandler(_)).WillOnce(Return());
EXPECT_CALL(dbusLoopMock, addSignalHandler(Eq(SIGUSR1), _))
.WillOnce(Return());
EXPECT_CALL(dbusLoopMock,
addPropertyHandler(StrEq(ConfigInTest::config.hostState), _, _))
.WillOnce(Return());
EXPECT_CALL(dbusLoopMock, run).WillOnce(Return(0));
EXPECT_CALL(logBufferMock, empty()).WillOnce(Return(false));
EXPECT_CALL(*this, flush()).WillOnce(Return());
EXPECT_NO_THROW(run());
}
} // namespace