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 "device.hpp"
17 #include "i2c_interface.hpp"
18 #include "id_map.hpp"
19 #include "mocked_i2c_interface.hpp"
20 #include "rail.hpp"
21 #include "rule.hpp"
22 
23 #include <exception>
24 #include <memory>
25 #include <stdexcept>
26 #include <string>
27 #include <utility>
28 #include <vector>
29 
30 #include <gtest/gtest.h>
31 
32 using namespace phosphor::power::regulators;
33 
34 TEST(IDMapTests, AddDevice)
35 {
36     IDMap idMap{};
37 
38     // Create device
39     std::unique_ptr<i2c::I2CInterface> i2cInterface =
40         i2c::create(1, 0x70, i2c::I2CInterface::InitialState::CLOSED);
41     std::string id{"vio_reg"};
42     Device device{
43         id, true,
44         "/xyz/openbmc_project/inventory/system/chassis/motherboard/vio_reg",
45         std::move(i2cInterface)};
46 
47     // Verify device is not initially in map
48     EXPECT_THROW(idMap.getDevice(id), std::invalid_argument);
49 
50     // Add device to map
51     idMap.addDevice(device);
52 
53     // Verify device is now in map
54     try
55     {
56         Device& deviceFound = idMap.getDevice(id);
57         EXPECT_EQ(deviceFound.getID(), id);
58         EXPECT_EQ(&deviceFound, &device);
59     }
60     catch (const std::exception& error)
61     {
62         ADD_FAILURE() << "Should not have caught exception.";
63     }
64 
65     // Verify different device is not in map
66     EXPECT_THROW(idMap.getDevice("vio_reg2"), std::invalid_argument);
67 
68     // Test where device ID already exists in map
69     try
70     {
71         i2cInterface =
72             i2c::create(1, 0x72, i2c::I2CInterface::InitialState::CLOSED);
73         Device device2{"vio_reg", true,
74                        "/xyz/openbmc_project/inventory/system/chassis/"
75                        "motherboard/vio_reg2",
76                        std::move(i2cInterface)};
77         idMap.addDevice(device2);
78         ADD_FAILURE() << "Should not have reached this line.";
79     }
80     catch (const std::invalid_argument& error)
81     {
82         EXPECT_STREQ(error.what(),
83                      "Unable to add device: Duplicate ID \"vio_reg\"");
84     }
85 }
86 
87 TEST(IDMapTests, AddRail)
88 {
89     IDMap idMap{};
90 
91     // Create rail
92     std::string id{"vio0"};
93     Rail rail{id};
94 
95     // Verify rail is not initially in map
96     EXPECT_THROW(idMap.getRail(id), std::invalid_argument);
97 
98     // Add rail to map
99     idMap.addRail(rail);
100 
101     // Verify rail is now in map
102     try
103     {
104         Rail& railFound = idMap.getRail(id);
105         EXPECT_EQ(railFound.getID(), id);
106         EXPECT_EQ(&railFound, &rail);
107     }
108     catch (const std::exception& error)
109     {
110         ADD_FAILURE() << "Should not have caught exception.";
111     }
112 
113     // Verify different rail is not in map
114     EXPECT_THROW(idMap.getRail("vcs0"), std::invalid_argument);
115 
116     // Test where rail ID already exists in map
117     try
118     {
119         Rail rail2{"vio0"};
120         idMap.addRail(rail2);
121         ADD_FAILURE() << "Should not have reached this line.";
122     }
123     catch (const std::invalid_argument& error)
124     {
125         EXPECT_STREQ(error.what(), "Unable to add rail: Duplicate ID \"vio0\"");
126     }
127 }
128 
129 TEST(IDMapTests, AddRule)
130 {
131     IDMap idMap{};
132 
133     // Create rule
134     std::string id{"set_voltage_rule"};
135     Rule rule{id, std::vector<std::unique_ptr<Action>>{}};
136 
137     // Verify rule is not initially in map
138     EXPECT_THROW(idMap.getRule(id), std::invalid_argument);
139 
140     // Add rule to map
141     idMap.addRule(rule);
142 
143     // Verify rule is now in map
144     try
145     {
146         Rule& ruleFound = idMap.getRule(id);
147         EXPECT_EQ(ruleFound.getID(), id);
148         EXPECT_EQ(&ruleFound, &rule);
149     }
150     catch (const std::exception& error)
151     {
152         ADD_FAILURE() << "Should not have caught exception.";
153     }
154 
155     // Verify different rule is not in map
156     EXPECT_THROW(idMap.getRule("set_voltage_rule_page0"),
157                  std::invalid_argument);
158 
159     // Test where rule ID already exists in map
160     try
161     {
162         Rule rule2{"set_voltage_rule", std::vector<std::unique_ptr<Action>>{}};
163         idMap.addRule(rule2);
164         ADD_FAILURE() << "Should not have reached this line.";
165     }
166     catch (const std::invalid_argument& error)
167     {
168         EXPECT_STREQ(error.what(),
169                      "Unable to add rule: Duplicate ID \"set_voltage_rule\"");
170     }
171 }
172 
173 TEST(IDMapTests, GetDevice)
174 {
175     IDMap idMap{};
176 
177     // Create device
178     std::unique_ptr<i2c::I2CInterface> i2cInterface =
179         i2c::create(1, 0x70, i2c::I2CInterface::InitialState::CLOSED);
180     std::string id{"vio_reg"};
181     Device device{
182         id, true,
183         "/xyz/openbmc_project/inventory/system/chassis/motherboard/vio_reg",
184         std::move(i2cInterface)};
185 
186     // Add a device to the map
187     idMap.addDevice(device);
188 
189     // Test where ID found in map
190     try
191     {
192         Device& deviceFound = idMap.getDevice(id);
193         EXPECT_EQ(deviceFound.getID(), id);
194         EXPECT_EQ(&deviceFound, &device);
195     }
196     catch (const std::exception& error)
197     {
198         ADD_FAILURE() << "Should not have caught exception.";
199     }
200 
201     // Test where ID not found in map
202     try
203     {
204         idMap.getDevice("vcs_reg");
205         ADD_FAILURE() << "Should not have reached this line.";
206     }
207     catch (const std::invalid_argument& ia_error)
208     {
209         EXPECT_STREQ(ia_error.what(),
210                      "Unable to find device with ID \"vcs_reg\"");
211     }
212     catch (const std::exception& error)
213     {
214         ADD_FAILURE() << "Should not have caught exception.";
215     }
216 }
217 
218 TEST(IDMapTests, GetRail)
219 {
220     IDMap idMap{};
221 
222     // Add a rail to the map
223     std::string id{"vio0"};
224     Rail rail{id};
225     idMap.addRail(rail);
226 
227     // Test where ID found in map
228     try
229     {
230         Rail& railFound = idMap.getRail(id);
231         EXPECT_EQ(railFound.getID(), id);
232         EXPECT_EQ(&railFound, &rail);
233     }
234     catch (const std::exception& error)
235     {
236         ADD_FAILURE() << "Should not have caught exception.";
237     }
238 
239     // Test where ID not found in map
240     try
241     {
242         idMap.getRail("vcs0");
243         ADD_FAILURE() << "Should not have reached this line.";
244     }
245     catch (const std::invalid_argument& ia_error)
246     {
247         EXPECT_STREQ(ia_error.what(), "Unable to find rail with ID \"vcs0\"");
248     }
249     catch (const std::exception& error)
250     {
251         ADD_FAILURE() << "Should not have caught exception.";
252     }
253 }
254 
255 TEST(IDMapTests, GetRule)
256 {
257     IDMap idMap{};
258 
259     // Add a rule to the map
260     std::string id{"set_voltage_rule"};
261     Rule rule{id, std::vector<std::unique_ptr<Action>>{}};
262     idMap.addRule(rule);
263 
264     // Test where ID found in map
265     try
266     {
267         Rule& ruleFound = idMap.getRule(id);
268         EXPECT_EQ(ruleFound.getID(), id);
269         EXPECT_EQ(&ruleFound, &rule);
270     }
271     catch (const std::exception& error)
272     {
273         ADD_FAILURE() << "Should not have caught exception.";
274     }
275 
276     // Test where ID not found in map
277     try
278     {
279         idMap.getRule("read_sensors_rule");
280         ADD_FAILURE() << "Should not have reached this line.";
281     }
282     catch (const std::invalid_argument& ia_error)
283     {
284         EXPECT_STREQ(ia_error.what(),
285                      "Unable to find rule with ID \"read_sensors_rule\"");
286     }
287     catch (const std::exception& error)
288     {
289         ADD_FAILURE() << "Should not have caught exception.";
290     }
291 }
292