1 /** 2 * Copyright © 2018 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include <fstream> 17 #include <gtest/gtest.h> 18 #include <experimental/filesystem> 19 #include "policy_table.hpp" 20 #include "policy_find.hpp" 21 22 using namespace ibm::logging; 23 namespace fs = std::experimental::filesystem; 24 25 static constexpr auto json = R"( 26 [ 27 { 28 "dtls":[ 29 { 30 "CEID":"ABCD1234", 31 "mod":"", 32 "msg":"Error ABCD1234" 33 } 34 ], 35 "err":"xyz.openbmc_project.Error.Test1" 36 }, 37 38 { 39 "dtls":[ 40 { 41 "CEID":"XYZ222", 42 "mod":"", 43 "msg":"Error XYZ222" 44 } 45 ], 46 "err":"xyz.openbmc_project.Error.Test2" 47 }, 48 49 { 50 "dtls":[ 51 { 52 "CEID":"AAAAAA", 53 "mod":"mod1", 54 "msg":"Error AAAAAA" 55 }, 56 { 57 "CEID":"BBBBBB", 58 "mod":"mod2", 59 "msg":"Error BBBBBB" 60 }, 61 { 62 "CEID":"CCCCCC", 63 "mod":"mod3", 64 "msg":"Error CCCCCC" 65 } 66 ], 67 "err":"xyz.openbmc_project.Error.Test3" 68 }, 69 70 { 71 "dtls":[ 72 { 73 "CEID":"DDDDDDDD", 74 "mod":"I2C", 75 "msg":"Error DDDDDDDD" 76 }, 77 { 78 "CEID":"EEEEEEEE", 79 "mod":"FSI", 80 "msg":"Error EEEEEEEE" 81 } 82 ], 83 "err":"xyz.openbmc_project.Error.Test4" 84 }, 85 86 { 87 "dtls":[ 88 { 89 "CEID":"FFFFFFFF", 90 "mod":"6D", 91 "msg":"Error FFFFFFFF" 92 } 93 ], 94 95 "err":"xyz.openbmc_project.Error.Test5" 96 }, 97 { 98 "dtls":[ 99 { 100 "CEID":"GGGGGGGG", 101 "mod":"RAIL_5", 102 "msg":"Error GGGGGGGG" 103 } 104 ], 105 106 "err":"xyz.openbmc_project.Error.Test6" 107 }, 108 { 109 "dtls":[ 110 { 111 "CEID":"HHHHHHHH", 112 "mod":"INPUT_42", 113 "msg":"Error HHHHHHHH" 114 } 115 ], 116 "err":"xyz.openbmc_project.Error.Test7" 117 } 118 ])"; 119 120 121 /** 122 * Helper class to write the above json to a file and then 123 * remove it when the tests are over. 124 */ 125 class PolicyTableTest : public ::testing::Test 126 { 127 protected: 128 129 virtual void SetUp() 130 { 131 char dir[] = {"./jsonTestXXXXXX"}; 132 133 jsonDir = mkdtemp(dir); 134 jsonFile = jsonDir / "policy.json"; 135 136 std::ofstream f{jsonFile}; 137 f << json; 138 } 139 140 virtual void TearDown() 141 { 142 fs::remove_all(jsonDir); 143 } 144 145 fs::path jsonDir; 146 fs::path jsonFile; 147 }; 148 149 150 /** 151 * Test finding entries in the policy table 152 */ 153 TEST_F(PolicyTableTest, TestTable) 154 { 155 policy::Table policy{jsonFile}; 156 ASSERT_EQ(policy.isLoaded(), true); 157 158 //////////////////////////////////// 159 //Basic search, no modifier 160 std::string err{"xyz.openbmc_project.Error.Test2"}; 161 std::string mod; 162 163 auto details = policy.find(err, mod); 164 ASSERT_EQ(static_cast<bool>(details), true); 165 if (details) 166 { 167 ASSERT_EQ((*details).get().ceid, "XYZ222"); 168 ASSERT_EQ((*details).get().msg, "Error XYZ222"); 169 } 170 171 ///////////////////////////////////// 172 //Not found 173 err = "foo"; 174 details = policy.find(err, mod); 175 ASSERT_EQ(static_cast<bool>(details), false); 176 177 ///////////////////////////////////// 178 //Test with a modifier 179 err = "xyz.openbmc_project.Error.Test3"; 180 mod = "mod3"; 181 182 details = policy.find(err, mod); 183 ASSERT_EQ(static_cast<bool>(details), true); 184 if (details) 185 { 186 ASSERT_EQ((*details).get().ceid, "CCCCCC"); 187 ASSERT_EQ((*details).get().msg, "Error CCCCCC"); 188 } 189 } 190 191 /** 192 * Test policy::find() that uses the data from a property 193 * map to find entries in the policy table. 194 */ 195 TEST_F(PolicyTableTest, TestFinder) 196 { 197 using namespace std::literals::string_literals; 198 199 policy::Table policy{jsonFile}; 200 ASSERT_EQ(policy.isLoaded(), true); 201 202 //A basic search with no modifier 203 { 204 DbusPropertyMap testProperties 205 { 206 {"Message"s, Value{"xyz.openbmc_project.Error.Test1"s}} 207 }; 208 209 auto values = policy::find(policy, testProperties); 210 ASSERT_EQ(std::get<policy::EIDField>(values), "ABCD1234"); 211 ASSERT_EQ(std::get<policy::MsgField>(values), "Error ABCD1234"); 212 } 213 214 //Use CALLOUT_INVENTORY_PATH from the AdditionalData property 215 { 216 std::vector<std::string> ad{ 217 "FOO=BAR"s, 218 "CALLOUT_INVENTORY_PATH=mod2"s}; 219 DbusPropertyMap testProperties 220 { 221 {"Message"s, Value{"xyz.openbmc_project.Error.Test3"s}}, 222 {"AdditionalData"s, ad} 223 }; 224 225 auto values = policy::find(policy, testProperties); 226 ASSERT_EQ(std::get<policy::EIDField>(values), "BBBBBB"); 227 ASSERT_EQ(std::get<policy::MsgField>(values), "Error BBBBBB"); 228 } 229 230 //Use an I2C DEVICE_PATH from the AdditionalData property 231 { 232 std::vector<std::string> ad{ 233 "FOO=BAR"s, 234 "CALLOUT_DEVICE_PATH=/some/i2c/path"s}; 235 DbusPropertyMap testProperties 236 { 237 {"Message"s, Value{"xyz.openbmc_project.Error.Test4"s}}, 238 {"AdditionalData"s, ad} 239 }; 240 241 auto values = policy::find(policy, testProperties); 242 ASSERT_EQ(std::get<policy::EIDField>(values), "DDDDDDDD"); 243 ASSERT_EQ(std::get<policy::MsgField>(values), "Error DDDDDDDD"); 244 } 245 246 //Use an FSI DEVICE_PATH from the AdditionalData property 247 { 248 std::vector<std::string> ad{ 249 "FOO=BAR"s, 250 "CALLOUT_DEVICE_PATH=/some/fsi/path"s}; 251 DbusPropertyMap testProperties 252 { 253 {"Message"s, Value{"xyz.openbmc_project.Error.Test4"s}}, 254 {"AdditionalData"s, ad} 255 }; 256 257 auto values = policy::find(policy, testProperties); 258 ASSERT_EQ(std::get<policy::EIDField>(values), "EEEEEEEE"); 259 ASSERT_EQ(std::get<policy::MsgField>(values), "Error EEEEEEEE"); 260 } 261 262 //Use PROCEDURE from the AdditionalData property 263 { 264 std::vector<std::string> ad{ 265 "FOO=BAR"s, 266 "PROCEDURE=109"s}; 267 DbusPropertyMap testProperties 268 { 269 {"Message"s, Value{"xyz.openbmc_project.Error.Test5"s}}, 270 {"AdditionalData"s, ad} 271 }; 272 273 auto values = policy::find(policy, testProperties); 274 ASSERT_EQ(std::get<policy::EIDField>(values), "FFFFFFFF"); 275 ASSERT_EQ(std::get<policy::MsgField>(values), "Error FFFFFFFF"); 276 } 277 278 //Use RAIL_NAME from the AdditionalData property 279 { 280 std::vector<std::string> ad{ 281 "FOO=BAR"s, 282 "RAIL_NAME=RAIL_5"s}; 283 DbusPropertyMap testProperties 284 { 285 {"Message"s, Value{"xyz.openbmc_project.Error.Test6"s}}, 286 {"AdditionalData"s, ad} 287 }; 288 289 auto values = policy::find(policy, testProperties); 290 ASSERT_EQ(std::get<policy::EIDField>(values), "GGGGGGGG"); 291 ASSERT_EQ(std::get<policy::MsgField>(values), "Error GGGGGGGG"); 292 } 293 294 //Use INPUT_NAME from the AdditionalData property 295 { 296 std::vector<std::string> ad{ 297 "FOO=BAR"s, 298 "INPUT_NAME=INPUT_42"s}; 299 DbusPropertyMap testProperties 300 { 301 {"Message"s, Value{"xyz.openbmc_project.Error.Test7"s}}, 302 {"AdditionalData"s, ad} 303 }; 304 305 auto values = policy::find(policy, testProperties); 306 ASSERT_EQ(std::get<policy::EIDField>(values), "HHHHHHHH"); 307 ASSERT_EQ(std::get<policy::MsgField>(values), "Error HHHHHHHH"); 308 } 309 310 //Test not finding an entry. 311 { 312 DbusPropertyMap testProperties 313 { 314 {"Message"s, Value{"hello world"s}} 315 }; 316 317 auto values = policy::find(policy, testProperties); 318 ASSERT_EQ(std::get<policy::EIDField>(values), policy.defaultEID()); 319 ASSERT_EQ(std::get<policy::MsgField>(values), policy.defaultMsg()); 320 } 321 322 // Test that strange AdditionalData values don't break anything 323 { 324 std::vector<std::string> ad{ 325 "FOO"s, 326 "INPUT_NAME="s}; 327 DbusPropertyMap testProperties 328 { 329 {"Message"s, Value{"xyz.openbmc_project.Error.Test7"s}}, 330 {"AdditionalData"s, ad} 331 }; 332 333 auto values = policy::find(policy, testProperties); 334 ASSERT_EQ(std::get<policy::EIDField>(values), policy.defaultEID()); 335 ASSERT_EQ(std::get<policy::MsgField>(values), policy.defaultMsg()); 336 } 337 } 338 339