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