xref: /openbmc/ibm-logging/test/test_policy.cpp (revision 66e0707365379e8716703e9175f82faa1f5b37ad)
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