1 #include "flags.hpp"
2 #include "image_mock.hpp"
3 #include "triggerable_mock.hpp"
4 #include "util.hpp"
5 #include "version_handler.hpp"
6 
7 #include <array>
8 #include <string>
9 #include <vector>
10 
11 #include <gtest/gtest.h>
12 using ::testing::_;
13 using ::testing::Return;
14 namespace ipmi_flash
15 {
16 
17 class VersionOpenBlobTest : public ::testing::Test
18 {
19   protected:
20     void SetUp() override
21     {
22         VersionInfoMap vim;
23         for (const auto& blobName : blobNames)
24         {
25             auto t = CreateTriggerMock();
26             auto i = CreateImageMock();
27             tm[blobName] = reinterpret_cast<TriggerMock*>(t.get());
28             im[blobName] = reinterpret_cast<ImageHandlerMock*>(i.get());
29             vim.try_emplace(
30                 blobName,
31                 VersionInfoPack(
32                     blobName, std::make_unique<VersionActionPack>(std::move(t)),
33                     std::move(i)));
34         }
35         h = VersionBlobHandler::create(std::move(vim));
36         ASSERT_NE(h, nullptr);
37         for (const auto& [key, val] : tm)
38         {
39             /* by default no action triggers expected to be called */
40             EXPECT_CALL(*val, trigger()).Times(0);
41         }
42         for (const auto& [key, val] : im)
43         {
44             /* by default no image handler open is expected to be called */
45             EXPECT_CALL(*val, open(_, _)).Times(0);
46         }
47     }
48     std::unique_ptr<blobs::GenericBlobInterface> h;
49     std::vector<std::string> blobNames{"blob0", "blob1", "blob2", "blob3"};
50     std::unordered_map<std::string, TriggerMock*> tm;
51     std::unordered_map<std::string, ImageHandlerMock*> im;
52     const std::uint16_t defaultSessionNumber{0};
53 };
54 
55 TEST_F(VersionOpenBlobTest, VerifySingleBlobOpen)
56 {
57     EXPECT_CALL(*tm.at("blob0"), trigger()).Times(1).WillOnce(Return(true));
58     EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
59 }
60 
61 TEST_F(VersionOpenBlobTest, VerifyMultipleBlobOpens)
62 {
63     for (const auto& [key, val] : tm)
64     {
65         /* set the expectation that every onOpen will be triggered */
66         EXPECT_CALL(*val, trigger()).Times(1).WillOnce(Return(true));
67     }
68     int i{defaultSessionNumber};
69     for (const auto& blob : blobNames)
70     {
71         EXPECT_TRUE(h->open(i++, blobs::read, blob));
72     }
73 }
74 
75 TEST_F(VersionOpenBlobTest, VerifyOpenAfterClose)
76 {
77     EXPECT_CALL(*tm.at("blob0"), trigger())
78         .Times(2)
79         .WillRepeatedly(Return(true));
80     EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
81     EXPECT_TRUE(h->close(defaultSessionNumber));
82     EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob0"));
83 }
84 
85 TEST_F(VersionOpenBlobTest, VerifyDuplicateSessionNumberFails)
86 {
87     EXPECT_CALL(*tm.at("blob0"), trigger()).Times(1).WillOnce(Return(true));
88     EXPECT_CALL(*tm.at("blob1"), trigger()).Times(1).WillOnce(Return(true));
89     EXPECT_TRUE(h->open(defaultSessionNumber, blobs::read, "blob1"));
90     /* the duplicate session number of 0
91      *  should cause a failure for the open of a different blob
92      */
93     EXPECT_FALSE(h->open(defaultSessionNumber, blobs::read, "blob0"));
94     /* open after fail due to seq number works */
95     EXPECT_TRUE(h->open(defaultSessionNumber + 1, blobs::read, "blob0"));
96 }
97 
98 TEST_F(VersionOpenBlobTest, VerifyDoubleOpenFails)
99 {
100     EXPECT_CALL(*tm.at("blob1"), trigger())
101         .Times(1)
102         .WillRepeatedly(Return(true));
103     EXPECT_TRUE(h->open(0, blobs::read, "blob1"));
104     EXPECT_FALSE(h->open(2, blobs::read, "blob1"));
105 }
106 
107 TEST_F(VersionOpenBlobTest, VerifyFailedTriggerFails)
108 {
109     EXPECT_CALL(*tm.at("blob1"), trigger())
110         .Times(2)
111         .WillOnce(Return(false))
112         .WillOnce(Return(true));
113     EXPECT_FALSE(h->open(0, blobs::read, "blob1"));
114     EXPECT_TRUE(h->open(0, blobs::read, "blob1"));
115 }
116 
117 TEST_F(VersionOpenBlobTest, VerifyUnsupportedOpenFlagsFails)
118 {
119     EXPECT_CALL(*tm.at("blob1"), trigger()).Times(1).WillOnce(Return(true));
120     EXPECT_FALSE(h->open(0, blobs::write, "blob1"));
121     EXPECT_TRUE(h->open(0, blobs::read, "blob1"));
122 }
123 
124 } // namespace ipmi_flash
125