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