1 #include "version_handler.hpp"
2 #include "version_mock.hpp"
3 
4 #include <memory>
5 #include <string>
6 #include <string_view>
7 #include <vector>
8 
9 #include <gtest/gtest.h>
10 
11 using ::testing::_;
12 using ::testing::DoAll;
13 using ::testing::ElementsAreArray;
14 using ::testing::Ge;
15 using ::testing::IsEmpty;
16 using ::testing::Return;
17 
18 namespace ipmi_flash
19 {
20 
21 class VersionReadBlobTest : public ::testing::Test
22 {
23   protected:
SetUp()24     void SetUp() override
25     {
26         h = std::make_unique<VersionBlobHandler>(
27             createMockVersionConfigs(blobNames, &im, &tm));
28     }
29     std::unique_ptr<blobs::GenericBlobInterface> h;
30     std::vector<std::string> blobNames{"blob0", "blob1", "blob2", "blob3"};
31     std::unordered_map<std::string, TriggerMock*> tm;
32     std::unordered_map<std::string, ImageHandlerMock*> im;
33     const std::uint16_t defaultSessionNumber{200};
34     std::vector<uint8_t> vector1{0xDE, 0xAD, 0xBE, 0xEF,
35                                  0xBA, 0xDF, 0xEE, 0x0D};
36     std::vector<uint8_t> vector2{0xCE, 0xAD, 0xDE, 0xFF};
37 };
38 
TEST_F(VersionReadBlobTest,VerifyValidRead)39 TEST_F(VersionReadBlobTest, VerifyValidRead)
40 {
41     testing::InSequence seq;
42     EXPECT_CALL(*tm.at("blob0"), trigger())
43         .WillOnce(DoAll([&]() { tm.at("blob0")->cb(*tm.at("blob0")); },
44                         Return(true)));
45     EXPECT_CALL(*tm.at("blob0"), status())
46         .WillOnce(Return(ActionStatus::success));
47     EXPECT_CALL(*im.at("blob0"), open(_, std::ios::in)).WillOnce(Return(true));
48     EXPECT_CALL(*im.at("blob0"), read(0, Ge(vector1.size())))
49         .WillOnce(Return(vector1));
50     EXPECT_CALL(*im.at("blob0"), close()).Times(1);
51     EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
52 
53     std::basic_string_view<uint8_t> vectorS(vector1.data(), vector1.size());
54     EXPECT_THAT(h->read(defaultSessionNumber, 0, 7),
55                 ElementsAreArray(vectorS.substr(0, 7)));
56     EXPECT_THAT(h->read(defaultSessionNumber, 2, 10),
57                 ElementsAreArray(vectorS.substr(2, 6)));
58     EXPECT_THAT(h->read(defaultSessionNumber, 10, 0), IsEmpty());
59 }
60 
TEST_F(VersionReadBlobTest,VerifyMultipleSession)61 TEST_F(VersionReadBlobTest, VerifyMultipleSession)
62 {
63     testing::InSequence seq;
64     EXPECT_CALL(*tm.at("blob0"), trigger()).WillOnce(Return(true));
65     EXPECT_TRUE(h->open(0, blobs::read, "blob0"));
66     EXPECT_TRUE(h->open(1, blobs::read, "blob0"));
67 
68     EXPECT_CALL(*tm.at("blob0"), status())
69         .WillOnce(Return(ActionStatus::success));
70     EXPECT_CALL(*im.at("blob0"), open(_, std::ios::in)).WillOnce(Return(true));
71     EXPECT_CALL(*im.at("blob0"), read(0, Ge(vector1.size())))
72         .WillOnce(Return(vector1));
73     EXPECT_CALL(*im.at("blob0"), close()).Times(1);
74     tm.at("blob0")->cb(*tm.at("blob0"));
75 
76     EXPECT_CALL(*tm.at("blob0"), trigger()).WillOnce(Return(true));
77     EXPECT_TRUE(h->open(2, blobs::read, "blob0"));
78 
79     EXPECT_CALL(*tm.at("blob0"), status())
80         .WillOnce(Return(ActionStatus::success));
81     EXPECT_CALL(*im.at("blob0"), open(_, std::ios::in)).WillOnce(Return(true));
82     EXPECT_CALL(*im.at("blob0"), read(0, Ge(vector2.size())))
83         .WillOnce(Return(vector2));
84     EXPECT_CALL(*im.at("blob0"), close()).Times(1);
85     tm.at("blob0")->cb(*tm.at("blob0"));
86 
87     EXPECT_THAT(h->read(0, 0, 10), ElementsAreArray(vector1));
88     EXPECT_THAT(h->read(1, 0, 10), ElementsAreArray(vector1));
89     EXPECT_THAT(h->read(2, 0, 10), ElementsAreArray(vector2));
90 }
91 
TEST_F(VersionReadBlobTest,VerifyReadEarlyFails)92 TEST_F(VersionReadBlobTest, VerifyReadEarlyFails)
93 {
94     EXPECT_CALL(*tm.at("blob0"), trigger()).WillOnce(Return(true));
95 
96     EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
97     EXPECT_THROW(h->read(defaultSessionNumber, 0, 10), std::runtime_error);
98 }
99 
TEST_F(VersionReadBlobTest,VerifyTriggerFailureReadFails)100 TEST_F(VersionReadBlobTest, VerifyTriggerFailureReadFails)
101 {
102     EXPECT_CALL(*tm.at("blob0"), trigger())
103         .WillOnce(DoAll([&]() { tm.at("blob0")->cb(*tm.at("blob0")); },
104                         Return(true)));
105     EXPECT_CALL(*tm.at("blob0"), status())
106         .WillOnce(Return(ActionStatus::failed));
107     EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
108     EXPECT_THROW(h->read(defaultSessionNumber, 0, 10), std::runtime_error);
109 }
110 
TEST_F(VersionReadBlobTest,VerifyReadFailsOnFileOpenFailure)111 TEST_F(VersionReadBlobTest, VerifyReadFailsOnFileOpenFailure)
112 {
113     EXPECT_CALL(*tm.at("blob0"), trigger())
114         .WillOnce(DoAll([&]() { tm.at("blob0")->cb(*tm.at("blob0")); },
115                         Return(true)));
116     EXPECT_CALL(*tm.at("blob0"), status())
117         .WillOnce(Return(ActionStatus::success));
118     EXPECT_CALL(*im.at("blob0"), open(_, std::ios::in)).WillOnce(Return(false));
119 
120     EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
121     EXPECT_THROW(h->read(defaultSessionNumber, 0, 10), std::runtime_error);
122 }
123 
TEST_F(VersionReadBlobTest,VerifyReadFailsOnFileReadFailure)124 TEST_F(VersionReadBlobTest, VerifyReadFailsOnFileReadFailure)
125 {
126     EXPECT_CALL(*tm.at("blob0"), trigger())
127         .WillOnce(DoAll([&]() { tm.at("blob0")->cb(*tm.at("blob0")); },
128                         Return(true)));
129     EXPECT_CALL(*tm.at("blob0"), status())
130         .WillOnce(Return(ActionStatus::success));
131     EXPECT_CALL(*im.at("blob0"), open(_, std::ios::in)).WillOnce(Return(true));
132     EXPECT_CALL(*im.at("blob0"), read(_, _)).WillOnce(Return(std::nullopt));
133     EXPECT_CALL(*im.at("blob0"), close()).Times(1);
134 
135     EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
136     EXPECT_THROW(h->read(defaultSessionNumber, 0, 10), std::runtime_error);
137 }
138 
139 } // namespace ipmi_flash
140