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 "policy_find.hpp" 17 #include "policy_table.hpp" 18 19 #include <experimental/filesystem> 20 #include <fstream> 21 22 #include <gtest/gtest.h> 23 24 using namespace ibm::logging; 25 namespace fs = std::experimental::filesystem; 26 27 static constexpr auto json = R"( 28 [ 29 { 30 "dtls":[ 31 { 32 "CEID":"ABCD1234", 33 "mod":"", 34 "msg":"Error ABCD1234" 35 } 36 ], 37 "err":"xyz.openbmc_project.Error.Test1" 38 }, 39 40 { 41 "dtls":[ 42 { 43 "CEID":"XYZ222", 44 "mod":"", 45 "msg":"Error XYZ222" 46 } 47 ], 48 "err":"xyz.openbmc_project.Error.Test2" 49 }, 50 51 { 52 "dtls":[ 53 { 54 "CEID":"AAAAAA", 55 "mod":"mod1", 56 "msg":"Error AAAAAA" 57 }, 58 { 59 "CEID":"BBBBBB", 60 "mod":"mod2", 61 "msg":"Error BBBBBB" 62 }, 63 { 64 "CEID":"CCCCCC", 65 "mod":"mod3", 66 "msg":"Error CCCCCC" 67 } 68 ], 69 "err":"xyz.openbmc_project.Error.Test3" 70 }, 71 72 { 73 "dtls":[ 74 { 75 "CEID":"DDDDDDDD", 76 "mod":"I2C", 77 "msg":"Error DDDDDDDD" 78 }, 79 { 80 "CEID":"EEEEEEEE", 81 "mod":"FSI", 82 "msg":"Error EEEEEEEE" 83 } 84 ], 85 "err":"xyz.openbmc_project.Error.Test4" 86 }, 87 88 { 89 "dtls":[ 90 { 91 "CEID":"FFFFFFFF", 92 "mod":"6D", 93 "msg":"Error FFFFFFFF" 94 } 95 ], 96 97 "err":"xyz.openbmc_project.Error.Test5" 98 }, 99 { 100 "dtls":[ 101 { 102 "CEID":"GGGGGGGG", 103 "mod":"RAIL_5", 104 "msg":"Error GGGGGGGG" 105 } 106 ], 107 108 "err":"xyz.openbmc_project.Error.Test6" 109 }, 110 { 111 "dtls":[ 112 { 113 "CEID":"HHHHHHHH", 114 "mod":"INPUT_42", 115 "msg":"Error HHHHHHHH" 116 } 117 ], 118 "err":"xyz.openbmc_project.Error.Test7" 119 } 120 ])"; 121 122 /** 123 * Helper class to write the above json to a file and then 124 * remove it when the tests are over. 125 */ 126 class PolicyTableTest : public ::testing::Test 127 { 128 protected: 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 * Test finding entries in the policy table 151 */ 152 TEST_F(PolicyTableTest, TestTable) 153 { 154 policy::Table policy{jsonFile}; 155 ASSERT_EQ(policy.isLoaded(), true); 156 157 //////////////////////////////////// 158 // Basic search, no modifier 159 std::string err{"xyz.openbmc_project.Error.Test2"}; 160 std::string mod; 161 162 auto details = policy.find(err, mod); 163 ASSERT_EQ(static_cast<bool>(details), true); 164 if (details) 165 { 166 ASSERT_EQ((*details).get().ceid, "XYZ222"); 167 ASSERT_EQ((*details).get().msg, "Error XYZ222"); 168 } 169 170 ///////////////////////////////////// 171 // Not found 172 err = "foo"; 173 details = policy.find(err, mod); 174 ASSERT_EQ(static_cast<bool>(details), false); 175 176 ///////////////////////////////////// 177 // Test with a modifier 178 err = "xyz.openbmc_project.Error.Test3"; 179 mod = "mod3"; 180 181 details = policy.find(err, mod); 182 ASSERT_EQ(static_cast<bool>(details), true); 183 if (details) 184 { 185 ASSERT_EQ((*details).get().ceid, "CCCCCC"); 186 ASSERT_EQ((*details).get().msg, "Error CCCCCC"); 187 } 188 } 189 190 /** 191 * Test policy::find() that uses the data from a property 192 * map to find entries in the policy table. 193 */ 194 TEST_F(PolicyTableTest, TestFinder) 195 { 196 using namespace std::literals::string_literals; 197 198 policy::Table policy{jsonFile}; 199 ASSERT_EQ(policy.isLoaded(), true); 200 201 // A basic search with no modifier 202 { 203 DbusPropertyMap testProperties{ 204 {"Message"s, Value{"xyz.openbmc_project.Error.Test1"s}}}; 205 206 auto values = policy::find(policy, testProperties); 207 ASSERT_EQ(std::get<policy::EIDField>(values), "ABCD1234"); 208 ASSERT_EQ(std::get<policy::MsgField>(values), "Error ABCD1234"); 209 } 210 211 // Use CALLOUT_INVENTORY_PATH from the AdditionalData property 212 { 213 std::vector<std::string> ad{"FOO=BAR"s, "CALLOUT_INVENTORY_PATH=mod2"s}; 214 DbusPropertyMap testProperties{ 215 {"Message"s, Value{"xyz.openbmc_project.Error.Test3"s}}, 216 {"AdditionalData"s, ad}}; 217 218 auto values = policy::find(policy, testProperties); 219 ASSERT_EQ(std::get<policy::EIDField>(values), "BBBBBB"); 220 ASSERT_EQ(std::get<policy::MsgField>(values), "Error BBBBBB"); 221 } 222 223 // Use an I2C DEVICE_PATH from the AdditionalData property 224 { 225 std::vector<std::string> ad{"FOO=BAR"s, 226 "CALLOUT_DEVICE_PATH=/some/i2c/path"s}; 227 DbusPropertyMap testProperties{ 228 {"Message"s, Value{"xyz.openbmc_project.Error.Test4"s}}, 229 {"AdditionalData"s, ad}}; 230 231 auto values = policy::find(policy, testProperties); 232 ASSERT_EQ(std::get<policy::EIDField>(values), "DDDDDDDD"); 233 ASSERT_EQ(std::get<policy::MsgField>(values), "Error DDDDDDDD"); 234 } 235 236 // Use an FSI DEVICE_PATH from the AdditionalData property 237 { 238 std::vector<std::string> ad{"FOO=BAR"s, 239 "CALLOUT_DEVICE_PATH=/some/fsi/path"s}; 240 DbusPropertyMap testProperties{ 241 {"Message"s, Value{"xyz.openbmc_project.Error.Test4"s}}, 242 {"AdditionalData"s, ad}}; 243 244 auto values = policy::find(policy, testProperties); 245 ASSERT_EQ(std::get<policy::EIDField>(values), "EEEEEEEE"); 246 ASSERT_EQ(std::get<policy::MsgField>(values), "Error EEEEEEEE"); 247 } 248 249 // Use PROCEDURE from the AdditionalData property 250 { 251 std::vector<std::string> ad{"FOO=BAR"s, "PROCEDURE=109"s}; 252 DbusPropertyMap testProperties{ 253 {"Message"s, Value{"xyz.openbmc_project.Error.Test5"s}}, 254 {"AdditionalData"s, ad}}; 255 256 auto values = policy::find(policy, testProperties); 257 ASSERT_EQ(std::get<policy::EIDField>(values), "FFFFFFFF"); 258 ASSERT_EQ(std::get<policy::MsgField>(values), "Error FFFFFFFF"); 259 } 260 261 // Use RAIL_NAME from the AdditionalData property 262 { 263 std::vector<std::string> ad{"FOO=BAR"s, "RAIL_NAME=RAIL_5"s}; 264 DbusPropertyMap testProperties{ 265 {"Message"s, Value{"xyz.openbmc_project.Error.Test6"s}}, 266 {"AdditionalData"s, ad}}; 267 268 auto values = policy::find(policy, testProperties); 269 ASSERT_EQ(std::get<policy::EIDField>(values), "GGGGGGGG"); 270 ASSERT_EQ(std::get<policy::MsgField>(values), "Error GGGGGGGG"); 271 } 272 273 // Use INPUT_NAME from the AdditionalData property 274 { 275 std::vector<std::string> ad{"FOO=BAR"s, "INPUT_NAME=INPUT_42"s}; 276 DbusPropertyMap testProperties{ 277 {"Message"s, Value{"xyz.openbmc_project.Error.Test7"s}}, 278 {"AdditionalData"s, ad}}; 279 280 auto values = policy::find(policy, testProperties); 281 ASSERT_EQ(std::get<policy::EIDField>(values), "HHHHHHHH"); 282 ASSERT_EQ(std::get<policy::MsgField>(values), "Error HHHHHHHH"); 283 } 284 285 // Test not finding an entry. 286 { 287 DbusPropertyMap testProperties{{"Message"s, Value{"hello world"s}}}; 288 289 auto values = policy::find(policy, testProperties); 290 ASSERT_EQ(std::get<policy::EIDField>(values), policy.defaultEID()); 291 ASSERT_EQ(std::get<policy::MsgField>(values), policy.defaultMsg()); 292 } 293 294 // Test that strange AdditionalData values don't break anything 295 { 296 std::vector<std::string> ad{"FOO"s, "INPUT_NAME="s}; 297 DbusPropertyMap testProperties{ 298 {"Message"s, Value{"xyz.openbmc_project.Error.Test7"s}}, 299 {"AdditionalData"s, ad}}; 300 301 auto values = policy::find(policy, testProperties); 302 ASSERT_EQ(std::get<policy::EIDField>(values), policy.defaultEID()); 303 ASSERT_EQ(std::get<policy::MsgField>(values), policy.defaultMsg()); 304 } 305 } 306