1 /**
2  * Copyright © 2019 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 "action_environment.hpp"
17 #include "device.hpp"
18 #include "i2c_interface.hpp"
19 #include "id_map.hpp"
20 #include "mock_services.hpp"
21 #include "mocked_i2c_interface.hpp"
22 #include "pmbus_utils.hpp"
23 #include "rule.hpp"
24 
25 #include <cstddef> // for size_t
26 #include <exception>
27 #include <memory>
28 #include <stdexcept>
29 #include <utility>
30 #include <vector>
31 
32 #include <gtest/gtest.h>
33 
34 using namespace phosphor::power::regulators;
35 
36 TEST(ActionEnvironmentTests, Constructor)
37 {
38     // Create IDMap
39     IDMap idMap{};
40 
41     // Create mock services.
42     MockServices services{};
43 
44     // Create Device and add to IDMap
45     std::unique_ptr<i2c::I2CInterface> i2cInterface =
46         i2c::create(1, 0x70, i2c::I2CInterface::InitialState::CLOSED);
47     Device reg1{
48         "regulator1", true,
49         "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
50         std::move(i2cInterface)};
51     idMap.addDevice(reg1);
52 
53     // Verify object state after constructor
54     try
55     {
56         ActionEnvironment env{idMap, "regulator1", services};
57         EXPECT_EQ(env.getDevice().getID(), "regulator1");
58         EXPECT_EQ(env.getDeviceID(), "regulator1");
59         EXPECT_EQ(env.getRuleDepth(), 0);
60         EXPECT_EQ(env.getVolts().has_value(), false);
61     }
62     catch (const std::exception& error)
63     {
64         ADD_FAILURE() << "Should not have caught exception.";
65     }
66 }
67 
68 TEST(ActionEnvironmentTests, AddSensorReading)
69 {
70     IDMap idMap{};
71     MockServices services{};
72     ActionEnvironment env{idMap, "", services};
73     pmbus_utils::SensorReading reading;
74     reading.type = pmbus_utils::SensorValueType::iout;
75     reading.value = 1;
76     EXPECT_EQ(env.getSensorReadings().size(), 0);
77     env.addSensorReading(reading);
78     EXPECT_EQ(env.getSensorReadings().size(), 1);
79     EXPECT_EQ(env.getSensorReadings()[0].type,
80               pmbus_utils::SensorValueType::iout);
81     EXPECT_EQ(env.getSensorReadings()[0].value, 1);
82     reading.type = pmbus_utils::SensorValueType::vout;
83     reading.value = 2;
84     env.addSensorReading(reading);
85     EXPECT_EQ(env.getSensorReadings().size(), 2);
86     EXPECT_EQ(env.getSensorReadings()[1].type,
87               pmbus_utils::SensorValueType::vout);
88     EXPECT_EQ(env.getSensorReadings()[1].value, 2);
89 }
90 
91 TEST(ActionEnvironmentTests, DecrementRuleDepth)
92 {
93     IDMap idMap{};
94     MockServices services{};
95     ActionEnvironment env{idMap, "", services};
96     EXPECT_EQ(env.getRuleDepth(), 0);
97     env.incrementRuleDepth("set_voltage_rule");
98     env.incrementRuleDepth("set_voltage_rule");
99     EXPECT_EQ(env.getRuleDepth(), 2);
100     env.decrementRuleDepth();
101     EXPECT_EQ(env.getRuleDepth(), 1);
102     env.decrementRuleDepth();
103     EXPECT_EQ(env.getRuleDepth(), 0);
104     env.decrementRuleDepth();
105     EXPECT_EQ(env.getRuleDepth(), 0);
106 }
107 
108 TEST(ActionEnvironmentTests, GetDevice)
109 {
110     // Create IDMap
111     IDMap idMap{};
112 
113     // Create mock services.
114     MockServices services{};
115 
116     // Create Device and add to IDMap
117     std::unique_ptr<i2c::I2CInterface> i2cInterface =
118         i2c::create(1, 0x70, i2c::I2CInterface::InitialState::CLOSED);
119     Device reg1{
120         "regulator1", true,
121         "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
122         std::move(i2cInterface)};
123     idMap.addDevice(reg1);
124 
125     ActionEnvironment env{idMap, "regulator1", services};
126 
127     // Test where current device ID is in the IDMap
128     try
129     {
130         Device& device = env.getDevice();
131         EXPECT_EQ(device.getID(), "regulator1");
132         EXPECT_EQ(&device, &reg1);
133     }
134     catch (const std::exception& error)
135     {
136         ADD_FAILURE() << "Should not have caught exception.";
137     }
138 
139     // Test where current device ID is not in the IDMap
140     env.setDeviceID("regulator2");
141     try
142     {
143         env.getDevice();
144         ADD_FAILURE() << "Should not have reached this line.";
145     }
146     catch (const std::invalid_argument& ia_error)
147     {
148         EXPECT_STREQ(ia_error.what(),
149                      "Unable to find device with ID \"regulator2\"");
150     }
151     catch (const std::exception& error)
152     {
153         ADD_FAILURE() << "Should not have caught exception.";
154     }
155 }
156 
157 TEST(ActionEnvironmentTests, GetDeviceID)
158 {
159     IDMap idMap{};
160     MockServices services{};
161     ActionEnvironment env{idMap, "", services};
162     EXPECT_EQ(env.getDeviceID(), "");
163     env.setDeviceID("regulator1");
164     EXPECT_EQ(env.getDeviceID(), "regulator1");
165 }
166 
167 TEST(ActionEnvironmentTests, GetRule)
168 {
169     // Create IDMap
170     IDMap idMap{};
171 
172     // Create mock services.
173     MockServices services{};
174 
175     Rule setVoltageRule{"set_voltage_rule",
176                         std::vector<std::unique_ptr<Action>>{}};
177     idMap.addRule(setVoltageRule);
178 
179     ActionEnvironment env{idMap, "", services};
180 
181     // Test where rule ID is in the IDMap
182     try
183     {
184         Rule& rule = env.getRule("set_voltage_rule");
185         EXPECT_EQ(rule.getID(), "set_voltage_rule");
186         EXPECT_EQ(&rule, &setVoltageRule);
187     }
188     catch (const std::exception& error)
189     {
190         ADD_FAILURE() << "Should not have caught exception.";
191     }
192 
193     // Test where rule ID is not in the IDMap
194     try
195     {
196         env.getRule("set_voltage_rule2");
197         ADD_FAILURE() << "Should not have reached this line.";
198     }
199     catch (const std::invalid_argument& ia_error)
200     {
201         EXPECT_STREQ(ia_error.what(),
202                      "Unable to find rule with ID \"set_voltage_rule2\"");
203     }
204     catch (const std::exception& error)
205     {
206         ADD_FAILURE() << "Should not have caught exception.";
207     }
208 }
209 
210 TEST(ActionEnvironmentTests, GetRuleDepth)
211 {
212     IDMap idMap{};
213     MockServices services{};
214     ActionEnvironment env{idMap, "", services};
215     EXPECT_EQ(env.getRuleDepth(), 0);
216     env.incrementRuleDepth("set_voltage_rule");
217     EXPECT_EQ(env.getRuleDepth(), 1);
218     env.incrementRuleDepth("set_voltage_rule");
219     EXPECT_EQ(env.getRuleDepth(), 2);
220     env.decrementRuleDepth();
221     EXPECT_EQ(env.getRuleDepth(), 1);
222     env.decrementRuleDepth();
223     EXPECT_EQ(env.getRuleDepth(), 0);
224 }
225 
226 TEST(ActionEnvironmentTests, GetSensorReadings)
227 {
228     IDMap idMap{};
229     MockServices services{};
230     ActionEnvironment env{idMap, "", services};
231     pmbus_utils::SensorReading reading;
232     reading.type = pmbus_utils::SensorValueType::pout;
233     reading.value = 1.3;
234     EXPECT_EQ(env.getSensorReadings().size(), 0);
235     env.addSensorReading(reading);
236     EXPECT_EQ(env.getSensorReadings().size(), 1);
237     EXPECT_EQ(env.getSensorReadings()[0].type,
238               pmbus_utils::SensorValueType::pout);
239     EXPECT_EQ(env.getSensorReadings()[0].value, 1.3);
240     reading.type = pmbus_utils::SensorValueType::temperature;
241     reading.value = -1;
242     env.addSensorReading(reading);
243     EXPECT_EQ(env.getSensorReadings().size(), 2);
244     EXPECT_EQ(env.getSensorReadings()[1].type,
245               pmbus_utils::SensorValueType::temperature);
246     EXPECT_EQ(env.getSensorReadings()[1].value, -1);
247 }
248 
249 TEST(ActionEnvironmentTests, GetServices)
250 {
251     IDMap idMap{};
252     MockServices services{};
253     ActionEnvironment env{idMap, "", services};
254     EXPECT_EQ(&(env.getServices()), &services);
255 }
256 
257 TEST(ActionEnvironmentTests, GetVolts)
258 {
259     IDMap idMap{};
260     MockServices services{};
261     ActionEnvironment env{idMap, "", services};
262     EXPECT_EQ(env.getVolts().has_value(), false);
263     env.setVolts(1.31);
264     EXPECT_EQ(env.getVolts().has_value(), true);
265     EXPECT_EQ(env.getVolts().value(), 1.31);
266 }
267 
268 TEST(ActionEnvironmentTests, IncrementRuleDepth)
269 {
270     IDMap idMap{};
271     MockServices services{};
272     ActionEnvironment env{idMap, "", services};
273     EXPECT_EQ(env.getRuleDepth(), 0);
274 
275     // Test where rule depth has not exceeded maximum
276     try
277     {
278         for (size_t i = 1; i <= env.maxRuleDepth; ++i)
279         {
280             env.incrementRuleDepth("set_voltage_rule");
281             EXPECT_EQ(env.getRuleDepth(), i);
282         }
283     }
284     catch (const std::exception& error)
285     {
286         ADD_FAILURE() << "Should not have caught exception.";
287     }
288 
289     // Test where rule depth has exceeded maximum
290     try
291     {
292         env.incrementRuleDepth("set_voltage_rule");
293     }
294     catch (const std::runtime_error& r_error)
295     {
296         EXPECT_STREQ(r_error.what(),
297                      "Maximum rule depth exceeded by rule set_voltage_rule.");
298     }
299     catch (const std::exception& error)
300     {
301         ADD_FAILURE() << "Should not have caught exception.";
302     }
303 }
304 
305 TEST(ActionEnvironmentTests, SetDeviceID)
306 {
307     IDMap idMap{};
308     MockServices services{};
309     ActionEnvironment env{idMap, "regulator1", services};
310     EXPECT_EQ(env.getDeviceID(), "regulator1");
311     env.setDeviceID("regulator2");
312     EXPECT_EQ(env.getDeviceID(), "regulator2");
313 }
314 
315 TEST(ActionEnvironmentTests, SetVolts)
316 {
317     try
318     {
319         IDMap idMap{};
320         MockServices services{};
321         ActionEnvironment env{idMap, "", services};
322         EXPECT_EQ(env.getVolts().has_value(), false);
323         env.setVolts(2.35);
324         EXPECT_EQ(env.getVolts().has_value(), true);
325         EXPECT_EQ(env.getVolts().value(), 2.35);
326     }
327     catch (const std::exception& error)
328     {
329         ADD_FAILURE() << "Should not have caught exception.";
330     }
331 }
332