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