1 #include "common/test/mocked_utils.hpp"
2 #include "libpldmresponder/bios_enum_attribute.hpp"
3 #include "mocked_bios.hpp"
4 
5 #include <nlohmann/json.hpp>
6 
7 #include <memory>
8 
9 #include <gmock/gmock.h>
10 #include <gtest/gtest.h>
11 
12 using namespace pldm::responder::bios;
13 using namespace pldm::utils;
14 
15 using ::testing::_;
16 using ::testing::ElementsAreArray;
17 using ::testing::Return;
18 using ::testing::StrEq;
19 using ::testing::Throw;
20 
21 class TestBIOSEnumAttribute : public ::testing::Test
22 {
23   public:
24     const auto& getPossibleValues(const BIOSEnumAttribute& attribute)
25     {
26         return attribute.possibleValues;
27     }
28 
29     const auto& getDefaultValue(const BIOSEnumAttribute& attribute)
30     {
31         return attribute.defaultValue;
32     }
33 };
34 
35 TEST_F(TestBIOSEnumAttribute, CtorTest)
36 {
37     auto jsonEnumReadOnly = R"({
38          "attribute_name" : "CodeUpdatePolicy",
39          "possible_values" : [ "Concurrent", "Disruptive" ],
40          "value_names" : [ "Concurrent", "Disruptive" ],
41          "default_values" : [ "Concurrent" ],
42          "readOnly" : true,
43          "helpText" : "HelpText",
44          "displayName" : "DisplayName"
45       })"_json;
46 
47     BIOSEnumAttribute enumReadOnly{jsonEnumReadOnly, nullptr};
48     EXPECT_EQ(enumReadOnly.name, "CodeUpdatePolicy");
49     EXPECT_TRUE(enumReadOnly.readOnly);
50     EXPECT_THAT(getPossibleValues(enumReadOnly),
51                 ElementsAreArray({"Concurrent", "Disruptive"}));
52     EXPECT_EQ(getDefaultValue(enumReadOnly), "Concurrent");
53 
54     auto jsonEnumReadOnlyError = R"({
55          "attribute_name" : "CodeUpdatePolicy",
56          "possible_value" : [ "Concurrent", "Disruptive" ],
57          "value_names" : [ "Concurrent", "Disruptive" ],
58          "default_values" : [ "Concurrent" ],
59          "readOnly" : true,
60          "helpText" : "HelpText",
61          "displayName" : "DisplayName"
62       })"_json; // possible_value -> possible_values
63     EXPECT_THROW((BIOSEnumAttribute{jsonEnumReadOnlyError, nullptr}),
64                  Json::exception);
65 
66     auto jsonEnumReadWrite = R"({
67          "attribute_name" : "FWBootSide",
68          "possible_values" : [ "Perm", "Temp" ],
69          "value_names" : [ "Perm", "Temp" ],
70          "default_values" : [ "Perm" ],
71          "readOnly" : false,
72          "helpText" : "HelpText",
73          "displayName" : "DisplayName",
74          "dbus":
75             {
76                "object_path" : "/xyz/abc/def",
77                "interface" : "xyz.openbmc.FWBoot.Side",
78                "property_name" : "Side",
79                "property_type" : "bool",
80                "property_values" : [true, false]
81             }
82       })"_json;
83 
84     BIOSEnumAttribute enumReadWrite{jsonEnumReadWrite, nullptr};
85     EXPECT_EQ(enumReadWrite.name, "FWBootSide");
86     EXPECT_TRUE(!enumReadWrite.readOnly);
87 }
88 
89 TEST_F(TestBIOSEnumAttribute, ConstructEntry)
90 {
91     MockBIOSStringTable biosStringTable;
92     MockdBusHandler dbusHandler;
93 
94     auto jsonEnumReadOnly = R"({
95          "attribute_name" : "CodeUpdatePolicy",
96          "possible_values" : [ "Concurrent", "Disruptive" ],
97          "value_names" : [ "Concurrent", "Disruptive" ],
98          "default_values" : [ "Disruptive" ],
99          "readOnly" : true,
100          "helpText" : "HelpText",
101          "displayName" : "DisplayName"
102       })"_json;
103 
104     std::vector<uint8_t> expectedAttrEntry{
105         0,    0, /* attr handle */
106         0x80,    /* attr type enum read-only*/
107         4,    0, /* attr name handle */
108         2,       /* number of possible value */
109         2,    0, /* possible value handle */
110         3,    0, /* possible value handle */
111         1,       /* number of default value */
112         1        /* defaut value string handle index */
113     };
114 
115     std::vector<uint8_t> expectedAttrValueEntry{
116         0, 0, /* attr handle */
117         0x80, /* attr type enum read-only*/
118         1,    /* number of current value */
119         1     /* current value string handle index */
120     };
121 
122     BIOSEnumAttribute enumReadOnly{jsonEnumReadOnly, nullptr};
123 
124     ON_CALL(biosStringTable, findHandle(StrEq("Concurrent")))
125         .WillByDefault(Return(2));
126     ON_CALL(biosStringTable, findHandle(StrEq("Disruptive")))
127         .WillByDefault(Return(3));
128     ON_CALL(biosStringTable, findHandle(StrEq("CodeUpdatePolicy")))
129         .WillByDefault(Return(4));
130 
131     checkConstructEntry(enumReadOnly, biosStringTable, expectedAttrEntry,
132                         expectedAttrValueEntry);
133 
134     auto jsonEnumReadWrite = R"({
135          "attribute_name" : "CodeUpdatePolicy",
136          "possible_values" : [ "Concurrent", "Disruptive" ],
137          "value_names" : [ "Concurrent", "Disruptive" ],
138          "default_values" : [ "Disruptive" ],
139          "readOnly" : false,
140          "helpText" : "HelpText",
141          "displayName" : "DisplayName",
142          "dbus":
143             {
144                "object_path" : "/xyz/abc/def",
145                "interface" : "xyz.openbmc.abc.def",
146                "property_name" : "Policy",
147                "property_type" : "bool",
148                "property_values" : [true, false]
149           }
150       })"_json;
151 
152     BIOSEnumAttribute enumReadWrite{jsonEnumReadWrite, &dbusHandler};
153 
154     EXPECT_CALL(dbusHandler,
155                 getDbusPropertyVariant(StrEq("/xyz/abc/def"), StrEq("Policy"),
156                                        StrEq("xyz.openbmc.abc.def")))
157         .WillOnce(Throw(std::exception()));
158 
159     /* Set expected attr type to read-write */
160     expectedAttrEntry[2] = PLDM_BIOS_ENUMERATION;
161     expectedAttrValueEntry[2] = PLDM_BIOS_ENUMERATION;
162 
163     checkConstructEntry(enumReadWrite, biosStringTable, expectedAttrEntry,
164                         expectedAttrValueEntry);
165 
166     EXPECT_CALL(dbusHandler,
167                 getDbusPropertyVariant(StrEq("/xyz/abc/def"), StrEq("Policy"),
168                                        StrEq("xyz.openbmc.abc.def")))
169         .WillOnce(Return(PropertyValue(true)));
170 
171     expectedAttrValueEntry = {
172         0, 0, /* attr handle */
173         0,    /* attr type enum read-write*/
174         1,    /* number of current value */
175         0     /* current value string handle index */
176     };
177 
178     checkConstructEntry(enumReadWrite, biosStringTable, expectedAttrEntry,
179                         expectedAttrValueEntry);
180 }
181 
182 TEST_F(TestBIOSEnumAttribute, setAttrValueOnDbus)
183 {
184     MockBIOSStringTable biosStringTable;
185     MockdBusHandler dbusHandler;
186 
187     auto jsonEnumReadWrite = R"({
188          "attribute_name" : "CodeUpdatePolicy",
189          "possible_values" : [ "Concurrent", "Disruptive" ],
190          "value_names" : [ "Concurrent", "Disruptive" ],
191          "default_values" : [ "Disruptive" ],
192          "readOnly" : false,
193          "helpText" : "HelpText",
194          "displayName" : "DisplayName",
195          "dbus":
196             {
197                "object_path" : "/xyz/abc/def",
198                "interface" : "xyz.openbmc.abc.def",
199                "property_name" : "Policy",
200                "property_type" : "bool",
201                "property_values" : [true, false]
202           }
203       })"_json;
204     DBusMapping dbusMapping{"/xyz/abc/def", "xyz.openbmc.abc.def", "Policy",
205                             "bool"};
206 
207     BIOSEnumAttribute enumReadWrite{jsonEnumReadWrite, &dbusHandler};
208 
209     std::vector<uint8_t> attrEntry{
210         0, 0, /* attr handle */
211         0,    /* attr type enum read-only*/
212         4, 0, /* attr name handle */
213         2,    /* number of possible value */
214         2, 0, /* possible value handle */
215         3, 0, /* possible value handle */
216         1,    /* number of default value */
217         1     /* defaut value string handle index */
218     };
219 
220     ON_CALL(biosStringTable, findString(2))
221         .WillByDefault(Return(std::string("Concurrent")));
222     ON_CALL(biosStringTable, findString(3))
223         .WillByDefault(Return(std::string("Disruptive")));
224 
225     std::vector<uint8_t> attrValueEntry{
226         0, 0, /* attr handle */
227         0,    /* attr type enum read-only*/
228         1,    /* number of current value */
229         0     /* current value string handle index */
230     };
231 
232     EXPECT_CALL(dbusHandler,
233                 setDbusProperty(dbusMapping, PropertyValue{bool(true)}))
234         .Times(1);
235     enumReadWrite.setAttrValueOnDbus(
236         reinterpret_cast<pldm_bios_attr_val_table_entry*>(
237             attrValueEntry.data()),
238         reinterpret_cast<pldm_bios_attr_table_entry*>(attrEntry.data()),
239         biosStringTable);
240 }
241