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