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