diff options
| author | Benjamin Fair <benjaminfair@google.com> | 2019-10-11 16:57:47 -0700 |
|---|---|---|
| committer | Benjamin Fair <benjaminfair@google.com> | 2019-11-21 15:09:48 -0800 |
| commit | 30d09a316b49a89a7ea01368911fc92d8260b5e6 (patch) | |
| tree | 129e755e7360b4717949833765060b0ca0052e77 /tools/test | |
| parent | f7ccadb0a1bd074d731244d45cf9e1b45a27e2f6 (diff) | |
| download | phosphor-ipmi-flash-30d09a316b49a89a7ea01368911fc92d8260b5e6.tar.gz phosphor-ipmi-flash-30d09a316b49a89a7ea01368911fc92d8260b5e6.zip | |
tools: add network bridge support
Add support to the host tool for sending the image data over a network
connection.
Signed-off-by: Benjamin Fair <benjaminfair@google.com>
Change-Id: I88630d79499254d6c80ceaa8c7721c241d394fc8
Diffstat (limited to 'tools/test')
| -rw-r--r-- | tools/test/Makefile.am | 4 | ||||
| -rw-r--r-- | tools/test/tools_net_unittest.cpp | 230 |
2 files changed, 234 insertions, 0 deletions
diff --git a/tools/test/Makefile.am b/tools/test/Makefile.am index c05654b..1fe35a0 100644 --- a/tools/test/Makefile.am +++ b/tools/test/Makefile.am @@ -18,6 +18,7 @@ AM_LDFLAGS = \ check_PROGRAMS = \ tools_bt_unittest \ tools_lpc_unittest \ + tools_net_unittest \ tools_updater_unittest \ tools_helper_unittest @@ -29,6 +30,9 @@ tools_bt_unittest_LDADD = $(top_builddir)/tools/libupdater.la tools_lpc_unittest_SOURCES = tools_lpc_unittest.cpp tools_lpc_unittest_LDADD = $(top_builddir)/tools/libupdater.la +tools_net_unittest_SOURCES = tools_net_unittest.cpp +tools_net_unittest_LDADD = $(top_builddir)/tools/libupdater.la + tools_updater_unittest_SOURCES = tools_updater_unittest.cpp tools_updater_unittest_LDADD = $(top_builddir)/tools/libupdater.la diff --git a/tools/test/tools_net_unittest.cpp b/tools/test/tools_net_unittest.cpp new file mode 100644 index 0000000..51556ff --- /dev/null +++ b/tools/test/tools_net_unittest.cpp @@ -0,0 +1,230 @@ +#include "data.hpp" +#include "internal_sys_mock.hpp" +#include "net.hpp" +#include "progress_mock.hpp" + +#include <cstring> +#include <ipmiblob/test/blob_interface_mock.hpp> + +#include <gtest/gtest.h> + +namespace host_tool +{ +namespace +{ + +using namespace std::literals; + +using ::testing::_; +using ::testing::AllOf; +using ::testing::ContainerEq; +using ::testing::Field; +using ::testing::Gt; +using ::testing::InSequence; +using ::testing::NotNull; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::SetErrnoAndReturn; +using ::testing::StrEq; + +class NetHandleTest : public ::testing::Test +{ + protected: + NetHandleTest() : handler(&blobMock, &progMock, host, port, &sysMock) + { + sa.sin6_family = AF_INET6; + sa.sin6_port = htons(622); + sa.sin6_flowinfo = 0; + sa.sin6_addr = in6addr_loopback; // ::1 + sa.sin6_scope_id = 0; + + addr.ai_family = AF_INET6; + addr.ai_socktype = SOCK_STREAM; + addr.ai_addr = reinterpret_cast<struct sockaddr*>(&sa); + addr.ai_addrlen = sizeof(sa); + addr.ai_protocol = 0; + addr.ai_next = nullptr; + } + + void expectOpenFile() + { + EXPECT_CALL(sysMock, open(StrEq(filePath.c_str()), _)) + .WillOnce(Return(inFd)); + EXPECT_CALL(sysMock, close(inFd)).WillOnce(Return(0)); + EXPECT_CALL(sysMock, getSize(StrEq(filePath.c_str()))) + .WillOnce(Return(fakeFileSize)); + + EXPECT_CALL(progMock, start(fakeFileSize)); + } + + void expectAddrInfo() + { + EXPECT_CALL( + sysMock, + getaddrinfo(StrEq(host), StrEq(port), + AllOf(Field(&addrinfo::ai_flags, AI_NUMERICHOST), + Field(&addrinfo::ai_family, AF_INET), + Field(&addrinfo::ai_socktype, SOCK_STREAM)), + NotNull())) + .WillOnce(DoAll(SetArgPointee<3>(&addr), Return(0))); + EXPECT_CALL(sysMock, freeaddrinfo(&addr)); + } + + void expectConnection() + { + EXPECT_CALL(sysMock, socket(AF_INET6, SOCK_STREAM, 0)) + .WillOnce(Return(connFd)); + EXPECT_CALL(sysMock, close(connFd)).WillOnce(Return(0)); + EXPECT_CALL(sysMock, + connect(connFd, reinterpret_cast<struct sockaddr*>(&sa), + sizeof(sa))) + .WillOnce(Return(0)); + } + + internal::InternalSysMock sysMock; + ipmiblob::BlobInterfaceMock blobMock; + ProgressMock progMock; + + const std::string host = "::1"s; + const std::string port = "622"s; + + struct sockaddr_in6 sa; + struct addrinfo addr; + + static constexpr std::uint16_t session = 0xbeef; + const std::string filePath = "/asdf"s; + static constexpr int inFd = 5; + static constexpr int connFd = 7; + static constexpr size_t fakeFileSize = 128; + static constexpr size_t chunkSize = 16; + + NetDataHandler handler; +}; + +TEST_F(NetHandleTest, openFileFail) +{ + EXPECT_CALL(sysMock, open(StrEq(filePath.c_str()), _)) + .WillOnce(SetErrnoAndReturn(EACCES, -1)); + + EXPECT_FALSE(handler.sendContents(filePath, session)); +} + +TEST_F(NetHandleTest, getSizeFail) +{ + EXPECT_CALL(sysMock, open(StrEq(filePath.c_str()), _)) + .WillOnce(Return(inFd)); + EXPECT_CALL(sysMock, close(inFd)).WillOnce(Return(0)); + EXPECT_CALL(sysMock, getSize(StrEq(filePath.c_str()))).WillOnce(Return(0)); + + EXPECT_FALSE(handler.sendContents(filePath, session)); +} + +TEST_F(NetHandleTest, getaddrinfoFail) +{ + expectOpenFile(); + + EXPECT_CALL(sysMock, + getaddrinfo(StrEq(host), StrEq(port), + AllOf(Field(&addrinfo::ai_flags, AI_NUMERICHOST), + Field(&addrinfo::ai_family, AF_INET), + Field(&addrinfo::ai_socktype, SOCK_STREAM)), + NotNull())) + .WillOnce(Return(EAI_ADDRFAMILY)); + + EXPECT_FALSE(handler.sendContents(filePath, session)); +} + +TEST_F(NetHandleTest, connectFail) +{ + expectOpenFile(); + expectAddrInfo(); + + EXPECT_CALL(sysMock, socket(AF_INET6, SOCK_STREAM, 0)) + .WillOnce(Return(connFd)); + EXPECT_CALL(sysMock, close(connFd)).WillOnce(Return(0)); + EXPECT_CALL( + sysMock, + connect(connFd, reinterpret_cast<struct sockaddr*>(&sa), sizeof(sa))) + .WillOnce(SetErrnoAndReturn(ECONNREFUSED, -1)); + + EXPECT_FALSE(handler.sendContents(filePath, session)); +} + +TEST_F(NetHandleTest, sendfileFail) +{ + expectOpenFile(); + expectAddrInfo(); + expectConnection(); + + EXPECT_CALL(sysMock, sendfile(connFd, inFd, Pointee(0), _)) + .WillOnce(SetErrnoAndReturn(ETIMEDOUT, -1)); + + EXPECT_FALSE(handler.sendContents(filePath, session)); +} + +TEST_F(NetHandleTest, successOneChunk) +{ + expectOpenFile(); + expectAddrInfo(); + expectConnection(); + + { + InSequence seq; + + EXPECT_CALL(sysMock, + sendfile(connFd, inFd, Pointee(0), Gt(fakeFileSize))) + .WillOnce( + DoAll(SetArgPointee<2>(fakeFileSize), Return(fakeFileSize))); + EXPECT_CALL(sysMock, sendfile(connFd, inFd, Pointee(fakeFileSize), + Gt(fakeFileSize))) + .WillOnce(Return(0)); + } + + struct ipmi_flash::ExtChunkHdr chunk; + chunk.length = fakeFileSize; + std::vector<std::uint8_t> chunkBytes(sizeof(chunk)); + std::memcpy(chunkBytes.data(), &chunk, sizeof(chunk)); + EXPECT_CALL(blobMock, writeBytes(session, 0, ContainerEq(chunkBytes))); + + EXPECT_CALL(progMock, updateProgress(fakeFileSize)); + + EXPECT_TRUE(handler.sendContents(filePath, session)); +} + +TEST_F(NetHandleTest, successMultiChunk) +{ + expectOpenFile(); + expectAddrInfo(); + expectConnection(); + + struct ipmi_flash::ExtChunkHdr chunk; + chunk.length = chunkSize; + std::vector<std::uint8_t> chunkBytes(sizeof(chunk)); + std::memcpy(chunkBytes.data(), &chunk, sizeof(chunk)); + + { + InSequence seq; + + for (std::uint32_t offset = 0; offset < fakeFileSize; + offset += chunkSize) + { + EXPECT_CALL(sysMock, + sendfile(connFd, inFd, Pointee(offset), Gt(chunkSize))) + .WillOnce(DoAll(SetArgPointee<2>(offset + chunkSize), + Return(chunkSize))); + + EXPECT_CALL(blobMock, + writeBytes(session, offset, ContainerEq(chunkBytes))); + EXPECT_CALL(progMock, updateProgress(chunkSize)); + } + EXPECT_CALL(sysMock, sendfile(connFd, inFd, Pointee(fakeFileSize), + Gt(chunkSize))) + .WillOnce(Return(0)); + } + + EXPECT_TRUE(handler.sendContents(filePath, session)); +} + +} // namespace +} // namespace host_tool |

