130d09a31SBenjamin Fair #include "data.hpp"
230d09a31SBenjamin Fair #include "internal_sys_mock.hpp"
330d09a31SBenjamin Fair #include "net.hpp"
430d09a31SBenjamin Fair #include "progress_mock.hpp"
530d09a31SBenjamin Fair
630d09a31SBenjamin Fair #include <ipmiblob/test/blob_interface_mock.hpp>
730d09a31SBenjamin Fair
89b37b095SPatrick Venture #include <cstring>
99b37b095SPatrick Venture
1030d09a31SBenjamin Fair #include <gtest/gtest.h>
1130d09a31SBenjamin Fair
1230d09a31SBenjamin Fair namespace host_tool
1330d09a31SBenjamin Fair {
1430d09a31SBenjamin Fair namespace
1530d09a31SBenjamin Fair {
1630d09a31SBenjamin Fair
1730d09a31SBenjamin Fair using namespace std::literals;
1830d09a31SBenjamin Fair
1930d09a31SBenjamin Fair using ::testing::_;
2030d09a31SBenjamin Fair using ::testing::AllOf;
2130d09a31SBenjamin Fair using ::testing::ContainerEq;
22382d2a0eSRui Zhang using ::testing::DoAll;
2330d09a31SBenjamin Fair using ::testing::Field;
249bb21e3eSWilliam A. Kennington III using ::testing::Ge;
2530d09a31SBenjamin Fair using ::testing::Gt;
2630d09a31SBenjamin Fair using ::testing::InSequence;
2730d09a31SBenjamin Fair using ::testing::NotNull;
2830d09a31SBenjamin Fair using ::testing::Pointee;
2930d09a31SBenjamin Fair using ::testing::Return;
3030d09a31SBenjamin Fair using ::testing::SetArgPointee;
3130d09a31SBenjamin Fair using ::testing::SetErrnoAndReturn;
3230d09a31SBenjamin Fair using ::testing::StrEq;
3330d09a31SBenjamin Fair
3430d09a31SBenjamin Fair class NetHandleTest : public ::testing::Test
3530d09a31SBenjamin Fair {
3630d09a31SBenjamin Fair protected:
NetHandleTest()3730d09a31SBenjamin Fair NetHandleTest() : handler(&blobMock, &progMock, host, port, &sysMock)
3830d09a31SBenjamin Fair {
3930d09a31SBenjamin Fair sa.sin6_family = AF_INET6;
4030d09a31SBenjamin Fair sa.sin6_port = htons(622);
4130d09a31SBenjamin Fair sa.sin6_flowinfo = 0;
4230d09a31SBenjamin Fair sa.sin6_addr = in6addr_loopback; // ::1
4330d09a31SBenjamin Fair sa.sin6_scope_id = 0;
4430d09a31SBenjamin Fair
4530d09a31SBenjamin Fair addr.ai_family = AF_INET6;
4630d09a31SBenjamin Fair addr.ai_socktype = SOCK_STREAM;
4730d09a31SBenjamin Fair addr.ai_addr = reinterpret_cast<struct sockaddr*>(&sa);
4830d09a31SBenjamin Fair addr.ai_addrlen = sizeof(sa);
4930d09a31SBenjamin Fair addr.ai_protocol = 0;
5030d09a31SBenjamin Fair addr.ai_next = nullptr;
5130d09a31SBenjamin Fair }
5230d09a31SBenjamin Fair
expectOpenFile()5330d09a31SBenjamin Fair void expectOpenFile()
5430d09a31SBenjamin Fair {
5530d09a31SBenjamin Fair EXPECT_CALL(sysMock, open(StrEq(filePath.c_str()), _))
5630d09a31SBenjamin Fair .WillOnce(Return(inFd));
5730d09a31SBenjamin Fair EXPECT_CALL(sysMock, close(inFd)).WillOnce(Return(0));
5830d09a31SBenjamin Fair EXPECT_CALL(sysMock, getSize(StrEq(filePath.c_str())))
5930d09a31SBenjamin Fair .WillOnce(Return(fakeFileSize));
6030d09a31SBenjamin Fair }
6130d09a31SBenjamin Fair
expectAddrInfo()6230d09a31SBenjamin Fair void expectAddrInfo()
6330d09a31SBenjamin Fair {
6430d09a31SBenjamin Fair EXPECT_CALL(
6530d09a31SBenjamin Fair sysMock,
6630d09a31SBenjamin Fair getaddrinfo(StrEq(host), StrEq(port),
6730d09a31SBenjamin Fair AllOf(Field(&addrinfo::ai_flags, AI_NUMERICHOST),
682aa55347SBenjamin Fair Field(&addrinfo::ai_family, AF_UNSPEC),
6930d09a31SBenjamin Fair Field(&addrinfo::ai_socktype, SOCK_STREAM)),
7030d09a31SBenjamin Fair NotNull()))
7130d09a31SBenjamin Fair .WillOnce(DoAll(SetArgPointee<3>(&addr), Return(0)));
7230d09a31SBenjamin Fair EXPECT_CALL(sysMock, freeaddrinfo(&addr));
7330d09a31SBenjamin Fair }
7430d09a31SBenjamin Fair
expectConnection()7530d09a31SBenjamin Fair void expectConnection()
7630d09a31SBenjamin Fair {
7730d09a31SBenjamin Fair EXPECT_CALL(sysMock, socket(AF_INET6, SOCK_STREAM, 0))
7830d09a31SBenjamin Fair .WillOnce(Return(connFd));
7930d09a31SBenjamin Fair EXPECT_CALL(sysMock, close(connFd)).WillOnce(Return(0));
8030d09a31SBenjamin Fair EXPECT_CALL(sysMock,
8130d09a31SBenjamin Fair connect(connFd, reinterpret_cast<struct sockaddr*>(&sa),
8230d09a31SBenjamin Fair sizeof(sa)))
8330d09a31SBenjamin Fair .WillOnce(Return(0));
8430d09a31SBenjamin Fair }
8530d09a31SBenjamin Fair
8630d09a31SBenjamin Fair internal::InternalSysMock sysMock;
8730d09a31SBenjamin Fair ipmiblob::BlobInterfaceMock blobMock;
8830d09a31SBenjamin Fair ProgressMock progMock;
8930d09a31SBenjamin Fair
9030d09a31SBenjamin Fair const std::string host = "::1"s;
9130d09a31SBenjamin Fair const std::string port = "622"s;
9230d09a31SBenjamin Fair
9330d09a31SBenjamin Fair struct sockaddr_in6 sa;
9430d09a31SBenjamin Fair struct addrinfo addr;
9530d09a31SBenjamin Fair
9630d09a31SBenjamin Fair static constexpr std::uint16_t session = 0xbeef;
9730d09a31SBenjamin Fair const std::string filePath = "/asdf"s;
9830d09a31SBenjamin Fair static constexpr int inFd = 5;
9930d09a31SBenjamin Fair static constexpr int connFd = 7;
10030d09a31SBenjamin Fair static constexpr size_t fakeFileSize = 128;
10130d09a31SBenjamin Fair static constexpr size_t chunkSize = 16;
10230d09a31SBenjamin Fair
10330d09a31SBenjamin Fair NetDataHandler handler;
10430d09a31SBenjamin Fair };
10530d09a31SBenjamin Fair
TEST_F(NetHandleTest,openFileFail)10630d09a31SBenjamin Fair TEST_F(NetHandleTest, openFileFail)
10730d09a31SBenjamin Fair {
10830d09a31SBenjamin Fair EXPECT_CALL(sysMock, open(StrEq(filePath.c_str()), _))
10930d09a31SBenjamin Fair .WillOnce(SetErrnoAndReturn(EACCES, -1));
11030d09a31SBenjamin Fair
11130d09a31SBenjamin Fair EXPECT_FALSE(handler.sendContents(filePath, session));
11230d09a31SBenjamin Fair }
11330d09a31SBenjamin Fair
TEST_F(NetHandleTest,getaddrinfoFail)11430d09a31SBenjamin Fair TEST_F(NetHandleTest, getaddrinfoFail)
11530d09a31SBenjamin Fair {
11630d09a31SBenjamin Fair expectOpenFile();
11730d09a31SBenjamin Fair
11830d09a31SBenjamin Fair EXPECT_CALL(sysMock,
11930d09a31SBenjamin Fair getaddrinfo(StrEq(host), StrEq(port),
12030d09a31SBenjamin Fair AllOf(Field(&addrinfo::ai_flags, AI_NUMERICHOST),
1212aa55347SBenjamin Fair Field(&addrinfo::ai_family, AF_UNSPEC),
12230d09a31SBenjamin Fair Field(&addrinfo::ai_socktype, SOCK_STREAM)),
12330d09a31SBenjamin Fair NotNull()))
12430d09a31SBenjamin Fair .WillOnce(Return(EAI_ADDRFAMILY));
12530d09a31SBenjamin Fair
12630d09a31SBenjamin Fair EXPECT_FALSE(handler.sendContents(filePath, session));
12730d09a31SBenjamin Fair }
12830d09a31SBenjamin Fair
TEST_F(NetHandleTest,connectFail)12930d09a31SBenjamin Fair TEST_F(NetHandleTest, connectFail)
13030d09a31SBenjamin Fair {
13130d09a31SBenjamin Fair expectOpenFile();
13230d09a31SBenjamin Fair expectAddrInfo();
13330d09a31SBenjamin Fair
13430d09a31SBenjamin Fair EXPECT_CALL(sysMock, socket(AF_INET6, SOCK_STREAM, 0))
13530d09a31SBenjamin Fair .WillOnce(Return(connFd));
13630d09a31SBenjamin Fair EXPECT_CALL(sysMock, close(connFd)).WillOnce(Return(0));
137*42a44c28SPatrick Williams EXPECT_CALL(sysMock,
138*42a44c28SPatrick Williams connect(connFd, reinterpret_cast<struct sockaddr*>(&sa),
139*42a44c28SPatrick Williams sizeof(sa)))
14030d09a31SBenjamin Fair .WillOnce(SetErrnoAndReturn(ECONNREFUSED, -1));
14130d09a31SBenjamin Fair
14230d09a31SBenjamin Fair EXPECT_FALSE(handler.sendContents(filePath, session));
14330d09a31SBenjamin Fair }
14430d09a31SBenjamin Fair
TEST_F(NetHandleTest,sendfileFail)14530d09a31SBenjamin Fair TEST_F(NetHandleTest, sendfileFail)
14630d09a31SBenjamin Fair {
14730d09a31SBenjamin Fair expectOpenFile();
14830d09a31SBenjamin Fair expectAddrInfo();
14930d09a31SBenjamin Fair expectConnection();
15030d09a31SBenjamin Fair
15130d09a31SBenjamin Fair EXPECT_CALL(sysMock, sendfile(connFd, inFd, Pointee(0), _))
15230d09a31SBenjamin Fair .WillOnce(SetErrnoAndReturn(ETIMEDOUT, -1));
15330d09a31SBenjamin Fair
15430d09a31SBenjamin Fair EXPECT_FALSE(handler.sendContents(filePath, session));
15530d09a31SBenjamin Fair }
15630d09a31SBenjamin Fair
TEST_F(NetHandleTest,successOneChunk)15730d09a31SBenjamin Fair TEST_F(NetHandleTest, successOneChunk)
15830d09a31SBenjamin Fair {
15930d09a31SBenjamin Fair expectOpenFile();
16030d09a31SBenjamin Fair expectAddrInfo();
16130d09a31SBenjamin Fair expectConnection();
16230d09a31SBenjamin Fair
16330d09a31SBenjamin Fair {
16430d09a31SBenjamin Fair InSequence seq;
16530d09a31SBenjamin Fair
16630d09a31SBenjamin Fair EXPECT_CALL(sysMock,
16730d09a31SBenjamin Fair sendfile(connFd, inFd, Pointee(0), Gt(fakeFileSize)))
16830d09a31SBenjamin Fair .WillOnce(
16930d09a31SBenjamin Fair DoAll(SetArgPointee<2>(fakeFileSize), Return(fakeFileSize)));
17030d09a31SBenjamin Fair EXPECT_CALL(sysMock, sendfile(connFd, inFd, Pointee(fakeFileSize),
17130d09a31SBenjamin Fair Gt(fakeFileSize)))
17230d09a31SBenjamin Fair .WillOnce(Return(0));
17330d09a31SBenjamin Fair }
17430d09a31SBenjamin Fair
17530d09a31SBenjamin Fair struct ipmi_flash::ExtChunkHdr chunk;
17630d09a31SBenjamin Fair chunk.length = fakeFileSize;
17730d09a31SBenjamin Fair std::vector<std::uint8_t> chunkBytes(sizeof(chunk));
17830d09a31SBenjamin Fair std::memcpy(chunkBytes.data(), &chunk, sizeof(chunk));
17930d09a31SBenjamin Fair EXPECT_CALL(blobMock, writeBytes(session, 0, ContainerEq(chunkBytes)));
18030d09a31SBenjamin Fair
18130d09a31SBenjamin Fair EXPECT_CALL(progMock, updateProgress(fakeFileSize));
18230d09a31SBenjamin Fair
18330d09a31SBenjamin Fair EXPECT_TRUE(handler.sendContents(filePath, session));
18430d09a31SBenjamin Fair }
18530d09a31SBenjamin Fair
TEST_F(NetHandleTest,successMultiChunk)18630d09a31SBenjamin Fair TEST_F(NetHandleTest, successMultiChunk)
18730d09a31SBenjamin Fair {
18830d09a31SBenjamin Fair expectOpenFile();
18930d09a31SBenjamin Fair expectAddrInfo();
19030d09a31SBenjamin Fair expectConnection();
19130d09a31SBenjamin Fair
19230d09a31SBenjamin Fair struct ipmi_flash::ExtChunkHdr chunk;
19330d09a31SBenjamin Fair chunk.length = chunkSize;
19430d09a31SBenjamin Fair std::vector<std::uint8_t> chunkBytes(sizeof(chunk));
19530d09a31SBenjamin Fair std::memcpy(chunkBytes.data(), &chunk, sizeof(chunk));
19630d09a31SBenjamin Fair
19730d09a31SBenjamin Fair {
19830d09a31SBenjamin Fair InSequence seq;
19930d09a31SBenjamin Fair
20030d09a31SBenjamin Fair for (std::uint32_t offset = 0; offset < fakeFileSize;
20130d09a31SBenjamin Fair offset += chunkSize)
20230d09a31SBenjamin Fair {
20330d09a31SBenjamin Fair EXPECT_CALL(sysMock,
20430d09a31SBenjamin Fair sendfile(connFd, inFd, Pointee(offset), Gt(chunkSize)))
20530d09a31SBenjamin Fair .WillOnce(DoAll(SetArgPointee<2>(offset + chunkSize),
20630d09a31SBenjamin Fair Return(chunkSize)));
20730d09a31SBenjamin Fair
20830d09a31SBenjamin Fair EXPECT_CALL(blobMock,
20930d09a31SBenjamin Fair writeBytes(session, offset, ContainerEq(chunkBytes)));
21030d09a31SBenjamin Fair EXPECT_CALL(progMock, updateProgress(chunkSize));
21130d09a31SBenjamin Fair }
21230d09a31SBenjamin Fair EXPECT_CALL(sysMock, sendfile(connFd, inFd, Pointee(fakeFileSize),
21330d09a31SBenjamin Fair Gt(chunkSize)))
21430d09a31SBenjamin Fair .WillOnce(Return(0));
21530d09a31SBenjamin Fair }
21630d09a31SBenjamin Fair
21730d09a31SBenjamin Fair EXPECT_TRUE(handler.sendContents(filePath, session));
21830d09a31SBenjamin Fair }
21930d09a31SBenjamin Fair
TEST_F(NetHandleTest,successFallback)2209bb21e3eSWilliam A. Kennington III TEST_F(NetHandleTest, successFallback)
2219bb21e3eSWilliam A. Kennington III {
2229bb21e3eSWilliam A. Kennington III expectOpenFile();
2239bb21e3eSWilliam A. Kennington III expectAddrInfo();
2249bb21e3eSWilliam A. Kennington III expectConnection();
2259bb21e3eSWilliam A. Kennington III
2269bb21e3eSWilliam A. Kennington III struct ipmi_flash::ExtChunkHdr chunk;
2279bb21e3eSWilliam A. Kennington III chunk.length = chunkSize;
2289bb21e3eSWilliam A. Kennington III std::vector<std::uint8_t> chunkBytes(sizeof(chunk));
2299bb21e3eSWilliam A. Kennington III std::memcpy(chunkBytes.data(), &chunk, sizeof(chunk));
2309bb21e3eSWilliam A. Kennington III
2319bb21e3eSWilliam A. Kennington III {
2329bb21e3eSWilliam A. Kennington III InSequence seq;
2339bb21e3eSWilliam A. Kennington III EXPECT_CALL(sysMock, sendfile(connFd, inFd, _, _))
2349bb21e3eSWilliam A. Kennington III .WillOnce([](int, int, off_t*, size_t) {
2359bb21e3eSWilliam A. Kennington III errno = EINVAL;
2369bb21e3eSWilliam A. Kennington III return -1;
2379bb21e3eSWilliam A. Kennington III });
2389bb21e3eSWilliam A. Kennington III
2399bb21e3eSWilliam A. Kennington III std::vector<uint8_t> chunk(chunkSize);
2409bb21e3eSWilliam A. Kennington III for (std::uint32_t offset = 0; offset < fakeFileSize;
2419bb21e3eSWilliam A. Kennington III offset += chunkSize)
2429bb21e3eSWilliam A. Kennington III {
2439bb21e3eSWilliam A. Kennington III for (size_t i = 0; i < chunkSize; ++i)
2449bb21e3eSWilliam A. Kennington III {
2459bb21e3eSWilliam A. Kennington III chunk[i] = i + offset;
2469bb21e3eSWilliam A. Kennington III }
2479bb21e3eSWilliam A. Kennington III EXPECT_CALL(sysMock, read(inFd, _, Ge(chunkSize)))
2489bb21e3eSWilliam A. Kennington III .WillOnce([chunk](int, void* buf, size_t) {
2499bb21e3eSWilliam A. Kennington III memcpy(buf, chunk.data(), chunkSize);
2509bb21e3eSWilliam A. Kennington III return chunkSize;
2519bb21e3eSWilliam A. Kennington III });
2529bb21e3eSWilliam A. Kennington III EXPECT_CALL(sysMock, send(connFd, _, chunkSize, 0))
2539bb21e3eSWilliam A. Kennington III .WillOnce([chunk](int, const void* data, size_t len, int) {
2549bb21e3eSWilliam A. Kennington III std::vector<uint8_t> dcopy(len);
2559bb21e3eSWilliam A. Kennington III memcpy(dcopy.data(), data, len);
2569bb21e3eSWilliam A. Kennington III EXPECT_THAT(dcopy, ContainerEq(chunk));
2579bb21e3eSWilliam A. Kennington III return chunkSize;
2589bb21e3eSWilliam A. Kennington III });
2599bb21e3eSWilliam A. Kennington III EXPECT_CALL(blobMock,
2609bb21e3eSWilliam A. Kennington III writeBytes(session, offset, ContainerEq(chunkBytes)));
2619bb21e3eSWilliam A. Kennington III EXPECT_CALL(progMock, updateProgress(chunkSize));
2629bb21e3eSWilliam A. Kennington III }
2639bb21e3eSWilliam A. Kennington III EXPECT_CALL(sysMock, read(inFd, _, Ge(chunkSize))).WillOnce(Return(0));
2649bb21e3eSWilliam A. Kennington III EXPECT_CALL(sysMock, send(connFd, _, 0, 0)).WillOnce(Return(0));
2659bb21e3eSWilliam A. Kennington III }
2669bb21e3eSWilliam A. Kennington III
2679bb21e3eSWilliam A. Kennington III EXPECT_TRUE(handler.sendContents(filePath, session));
2689bb21e3eSWilliam A. Kennington III }
2699bb21e3eSWilliam A. Kennington III
27030d09a31SBenjamin Fair } // namespace
27130d09a31SBenjamin Fair } // namespace host_tool
272