xref: /openbmc/ibm-logging/test/test_policy.cpp (revision 259e7277)
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  * Helper class to write the above json to a file and then
122  * remove it when the tests are over.
123  */
124 class PolicyTableTest : public ::testing::Test
125 {
126   protected:
127     virtual void SetUp()
128     {
129         char dir[] = {"./jsonTestXXXXXX"};
130 
131         jsonDir = mkdtemp(dir);
132         jsonFile = jsonDir / "policy.json";
133 
134         std::ofstream f{jsonFile};
135         f << json;
136     }
137 
138     virtual void TearDown()
139     {
140         fs::remove_all(jsonDir);
141     }
142 
143     fs::path jsonDir;
144     fs::path jsonFile;
145 };
146 
147 /**
148  * Test finding entries in the policy table
149  */
150 TEST_F(PolicyTableTest, TestTable)
151 {
152     policy::Table policy{jsonFile};
153     ASSERT_EQ(policy.isLoaded(), true);
154 
155     ////////////////////////////////////
156     // Basic search, no modifier
157     std::string err{"xyz.openbmc_project.Error.Test2"};
158     std::string mod;
159 
160     auto details = policy.find(err, mod);
161     ASSERT_EQ(static_cast<bool>(details), true);
162     if (details)
163     {
164         ASSERT_EQ((*details).get().ceid, "XYZ222");
165         ASSERT_EQ((*details).get().msg, "Error XYZ222");
166     }
167 
168     /////////////////////////////////////
169     // Not found
170     err = "foo";
171     details = policy.find(err, mod);
172     ASSERT_EQ(static_cast<bool>(details), false);
173 
174     /////////////////////////////////////
175     // Test with a modifier
176     err = "xyz.openbmc_project.Error.Test3";
177     mod = "mod3";
178 
179     details = policy.find(err, mod);
180     ASSERT_EQ(static_cast<bool>(details), true);
181     if (details)
182     {
183         ASSERT_EQ((*details).get().ceid, "CCCCCC");
184         ASSERT_EQ((*details).get().msg, "Error CCCCCC");
185     }
186 }
187 
188 /**
189  * Test policy::find() that uses the data from a property
190  * map to find entries in the policy table.
191  */
192 TEST_F(PolicyTableTest, TestFinder)
193 {
194     using namespace std::literals::string_literals;
195 
196     policy::Table policy{jsonFile};
197     ASSERT_EQ(policy.isLoaded(), true);
198 
199     // A basic search with no modifier
200     {
201         DbusPropertyMap testProperties{
202             {"Message"s, Value{"xyz.openbmc_project.Error.Test1"s}}};
203 
204         auto values = policy::find(policy, testProperties);
205         ASSERT_EQ(std::get<policy::EIDField>(values), "ABCD1234");
206         ASSERT_EQ(std::get<policy::MsgField>(values), "Error ABCD1234");
207     }
208 
209     // Use CALLOUT_INVENTORY_PATH from the AdditionalData property
210     {
211         std::vector<std::string> ad{"FOO=BAR"s, "CALLOUT_INVENTORY_PATH=mod2"s};
212         DbusPropertyMap testProperties{
213             {"Message"s, Value{"xyz.openbmc_project.Error.Test3"s}},
214             {"AdditionalData"s, ad}};
215 
216         auto values = policy::find(policy, testProperties);
217         ASSERT_EQ(std::get<policy::EIDField>(values), "BBBBBB");
218         ASSERT_EQ(std::get<policy::MsgField>(values), "Error BBBBBB");
219     }
220 
221     // Use an I2C DEVICE_PATH from the AdditionalData property
222     {
223         std::vector<std::string> ad{"FOO=BAR"s,
224                                     "CALLOUT_DEVICE_PATH=/some/i2c/path"s};
225         DbusPropertyMap testProperties{
226             {"Message"s, Value{"xyz.openbmc_project.Error.Test4"s}},
227             {"AdditionalData"s, ad}};
228 
229         auto values = policy::find(policy, testProperties);
230         ASSERT_EQ(std::get<policy::EIDField>(values), "DDDDDDDD");
231         ASSERT_EQ(std::get<policy::MsgField>(values), "Error DDDDDDDD");
232     }
233 
234     // Use an FSI DEVICE_PATH from the AdditionalData property
235     {
236         std::vector<std::string> ad{"FOO=BAR"s,
237                                     "CALLOUT_DEVICE_PATH=/some/fsi/path"s};
238         DbusPropertyMap testProperties{
239             {"Message"s, Value{"xyz.openbmc_project.Error.Test4"s}},
240             {"AdditionalData"s, ad}};
241 
242         auto values = policy::find(policy, testProperties);
243         ASSERT_EQ(std::get<policy::EIDField>(values), "EEEEEEEE");
244         ASSERT_EQ(std::get<policy::MsgField>(values), "Error EEEEEEEE");
245     }
246 
247     // Use PROCEDURE from the AdditionalData property
248     {
249         std::vector<std::string> ad{"FOO=BAR"s, "PROCEDURE=109"s};
250         DbusPropertyMap testProperties{
251             {"Message"s, Value{"xyz.openbmc_project.Error.Test5"s}},
252             {"AdditionalData"s, ad}};
253 
254         auto values = policy::find(policy, testProperties);
255         ASSERT_EQ(std::get<policy::EIDField>(values), "FFFFFFFF");
256         ASSERT_EQ(std::get<policy::MsgField>(values), "Error FFFFFFFF");
257     }
258 
259     // Use RAIL_NAME from the AdditionalData property
260     {
261         std::vector<std::string> ad{"FOO=BAR"s, "RAIL_NAME=RAIL_5"s};
262         DbusPropertyMap testProperties{
263             {"Message"s, Value{"xyz.openbmc_project.Error.Test6"s}},
264             {"AdditionalData"s, ad}};
265 
266         auto values = policy::find(policy, testProperties);
267         ASSERT_EQ(std::get<policy::EIDField>(values), "GGGGGGGG");
268         ASSERT_EQ(std::get<policy::MsgField>(values), "Error GGGGGGGG");
269     }
270 
271     // Use INPUT_NAME from the AdditionalData property
272     {
273         std::vector<std::string> ad{"FOO=BAR"s, "INPUT_NAME=INPUT_42"s};
274         DbusPropertyMap testProperties{
275             {"Message"s, Value{"xyz.openbmc_project.Error.Test7"s}},
276             {"AdditionalData"s, ad}};
277 
278         auto values = policy::find(policy, testProperties);
279         ASSERT_EQ(std::get<policy::EIDField>(values), "HHHHHHHH");
280         ASSERT_EQ(std::get<policy::MsgField>(values), "Error HHHHHHHH");
281     }
282 
283     // Test not finding an entry.
284     {
285         DbusPropertyMap testProperties{{"Message"s, Value{"hello world"s}}};
286 
287         auto values = policy::find(policy, testProperties);
288         ASSERT_EQ(std::get<policy::EIDField>(values), policy.defaultEID());
289         ASSERT_EQ(std::get<policy::MsgField>(values), policy.defaultMsg());
290     }
291 
292     // Test that strange AdditionalData values don't break anything
293     {
294         std::vector<std::string> ad{"FOO"s, "INPUT_NAME="s};
295         DbusPropertyMap testProperties{
296             {"Message"s, Value{"xyz.openbmc_project.Error.Test7"s}},
297             {"AdditionalData"s, ad}};
298 
299         auto values = policy::find(policy, testProperties);
300         ASSERT_EQ(std::get<policy::EIDField>(values), policy.defaultEID());
301         ASSERT_EQ(std::get<policy::MsgField>(values), policy.defaultMsg());
302     }
303 }
304