xref: /openbmc/phosphor-ipmi-flash/tools/test/tools_net_unittest.cpp (revision 42a44c281cce08be0ca6251955f4fb73d30c8ced)
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