1 // Copyright 2021 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "log_handler.hpp"
16 #include "log_mock.hpp"
17
18 #include <memory>
19 #include <string>
20 #include <string_view>
21 #include <vector>
22
23 #include <gtest/gtest.h>
24
25 using ::testing::_;
26 using ::testing::DoAll;
27 using ::testing::ElementsAreArray;
28 using ::testing::Ge;
29 using ::testing::IsEmpty;
30 using ::testing::Return;
31
32 namespace ipmi_flash
33 {
34
35 class LogReadBlobTest : public ::testing::Test
36 {
37 protected:
SetUp()38 void SetUp() override
39 {
40 h = std::make_unique<LogBlobHandler>(
41 createMockLogConfigs(blobNames, &im, &tm));
42 }
43 std::unique_ptr<blobs::GenericBlobInterface> h;
44 std::vector<std::string> blobNames{"blob0", "blob1", "blob2", "blob3"};
45 std::unordered_map<std::string, TriggerMock*> tm;
46 std::unordered_map<std::string, ImageHandlerMock*> im;
47 const std::uint16_t defaultSessionNumber{200};
48 std::vector<uint8_t> vector1{0xDE, 0xAD, 0xBE, 0xEF,
49 0xBA, 0xDF, 0xEE, 0x0D};
50 std::vector<uint8_t> vector2{0xCE, 0xAD, 0xDE, 0xFF};
51 };
52
TEST_F(LogReadBlobTest,VerifyValidRead)53 TEST_F(LogReadBlobTest, VerifyValidRead)
54 {
55 testing::InSequence seq;
56 EXPECT_CALL(*tm.at("blob0"), trigger())
57 .WillOnce(DoAll([&]() { tm.at("blob0")->cb(*tm.at("blob0")); },
58 Return(true)));
59 EXPECT_CALL(*tm.at("blob0"), status())
60 .WillOnce(Return(ActionStatus::success));
61 EXPECT_CALL(*im.at("blob0"), open(_, std::ios::in)).WillOnce(Return(true));
62 EXPECT_CALL(*im.at("blob0"), read(0, Ge(vector1.size())))
63 .WillOnce(Return(vector1));
64 EXPECT_CALL(*im.at("blob0"), close()).Times(1);
65 EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
66
67 std::basic_string_view<uint8_t> vectorS(vector1.data(), vector1.size());
68 EXPECT_THAT(h->read(defaultSessionNumber, 0, 7),
69 ElementsAreArray(vectorS.substr(0, 7)));
70 EXPECT_THAT(h->read(defaultSessionNumber, 2, 10),
71 ElementsAreArray(vectorS.substr(2, 6)));
72 EXPECT_THAT(h->read(defaultSessionNumber, 10, 0), IsEmpty());
73 }
74
TEST_F(LogReadBlobTest,VerifyMultipleSession)75 TEST_F(LogReadBlobTest, VerifyMultipleSession)
76 {
77 testing::InSequence seq;
78 EXPECT_CALL(*tm.at("blob0"), trigger()).WillOnce(Return(true));
79 EXPECT_TRUE(h->open(0, blobs::read, "blob0"));
80 EXPECT_TRUE(h->open(1, blobs::read, "blob0"));
81
82 EXPECT_CALL(*tm.at("blob0"), status())
83 .WillOnce(Return(ActionStatus::success));
84 EXPECT_CALL(*im.at("blob0"), open(_, std::ios::in)).WillOnce(Return(true));
85 EXPECT_CALL(*im.at("blob0"), read(0, Ge(vector1.size())))
86 .WillOnce(Return(vector1));
87 EXPECT_CALL(*im.at("blob0"), close()).Times(1);
88 tm.at("blob0")->cb(*tm.at("blob0"));
89
90 EXPECT_CALL(*tm.at("blob0"), trigger()).WillOnce(Return(true));
91 EXPECT_TRUE(h->open(2, blobs::read, "blob0"));
92
93 EXPECT_CALL(*tm.at("blob0"), status())
94 .WillOnce(Return(ActionStatus::success));
95 EXPECT_CALL(*im.at("blob0"), open(_, std::ios::in)).WillOnce(Return(true));
96 EXPECT_CALL(*im.at("blob0"), read(0, Ge(vector2.size())))
97 .WillOnce(Return(vector2));
98 EXPECT_CALL(*im.at("blob0"), close()).Times(1);
99 tm.at("blob0")->cb(*tm.at("blob0"));
100
101 EXPECT_THAT(h->read(0, 0, 10), ElementsAreArray(vector1));
102 EXPECT_THAT(h->read(1, 0, 10), ElementsAreArray(vector1));
103 EXPECT_THAT(h->read(2, 0, 10), ElementsAreArray(vector2));
104 }
105
TEST_F(LogReadBlobTest,VerifyReadEarlyFails)106 TEST_F(LogReadBlobTest, VerifyReadEarlyFails)
107 {
108 EXPECT_CALL(*tm.at("blob0"), trigger()).WillOnce(Return(true));
109
110 EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
111 EXPECT_THROW(h->read(defaultSessionNumber, 0, 10), std::runtime_error);
112 }
113
TEST_F(LogReadBlobTest,VerifyTriggerFailureReadFails)114 TEST_F(LogReadBlobTest, VerifyTriggerFailureReadFails)
115 {
116 EXPECT_CALL(*tm.at("blob0"), trigger())
117 .WillOnce(DoAll([&]() { tm.at("blob0")->cb(*tm.at("blob0")); },
118 Return(true)));
119 EXPECT_CALL(*tm.at("blob0"), status())
120 .WillOnce(Return(ActionStatus::failed));
121 EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
122 EXPECT_THROW(h->read(defaultSessionNumber, 0, 10), std::runtime_error);
123 }
124
TEST_F(LogReadBlobTest,VerifyReadFailsOnFileOpenFailure)125 TEST_F(LogReadBlobTest, VerifyReadFailsOnFileOpenFailure)
126 {
127 EXPECT_CALL(*tm.at("blob0"), trigger())
128 .WillOnce(DoAll([&]() { tm.at("blob0")->cb(*tm.at("blob0")); },
129 Return(true)));
130 EXPECT_CALL(*tm.at("blob0"), status())
131 .WillOnce(Return(ActionStatus::success));
132 EXPECT_CALL(*im.at("blob0"), open(_, std::ios::in)).WillOnce(Return(false));
133
134 EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
135 EXPECT_THROW(h->read(defaultSessionNumber, 0, 10), std::runtime_error);
136 }
137
TEST_F(LogReadBlobTest,VerifyReadFailsOnFileReadFailure)138 TEST_F(LogReadBlobTest, VerifyReadFailsOnFileReadFailure)
139 {
140 EXPECT_CALL(*tm.at("blob0"), trigger())
141 .WillOnce(DoAll([&]() { tm.at("blob0")->cb(*tm.at("blob0")); },
142 Return(true)));
143 EXPECT_CALL(*tm.at("blob0"), status())
144 .WillOnce(Return(ActionStatus::success));
145 EXPECT_CALL(*im.at("blob0"), open(_, std::ios::in)).WillOnce(Return(true));
146 EXPECT_CALL(*im.at("blob0"), read(_, _)).WillOnce(Return(std::nullopt));
147 EXPECT_CALL(*im.at("blob0"), close()).Times(1);
148
149 EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
150 EXPECT_THROW(h->read(defaultSessionNumber, 0, 10), std::runtime_error);
151 }
152
153 } // namespace ipmi_flash
154