1 /**
2  * Copyright © 2020 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.hpp"
17 #include "chassis.hpp"
18 #include "configuration.hpp"
19 #include "device.hpp"
20 #include "i2c_interface.hpp"
21 #include "id_map.hpp"
22 #include "journal.hpp"
23 #include "mock_journal.hpp"
24 #include "presence_detection.hpp"
25 #include "rail.hpp"
26 #include "rule.hpp"
27 #include "system.hpp"
28 #include "test_utils.hpp"
29 
30 #include <memory>
31 #include <stdexcept>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 
36 #include <gtest/gtest.h>
37 
38 using namespace phosphor::power::regulators;
39 using namespace phosphor::power::regulators::test_utils;
40 
41 TEST(ChassisTests, Constructor)
42 {
43     // Test where works: Only required parameters are specified
44     {
45         Chassis chassis{2};
46         EXPECT_EQ(chassis.getNumber(), 2);
47         EXPECT_EQ(chassis.getDevices().size(), 0);
48     }
49 
50     // Test where works: All parameters are specified
51     {
52         // Create vector of Device objects
53         std::vector<std::unique_ptr<Device>> devices{};
54         devices.emplace_back(createDevice("vdd_reg1"));
55         devices.emplace_back(createDevice("vdd_reg2"));
56 
57         // Create Chassis
58         Chassis chassis{1, std::move(devices)};
59         EXPECT_EQ(chassis.getNumber(), 1);
60         EXPECT_EQ(chassis.getDevices().size(), 2);
61     }
62 
63     // Test where fails: Invalid chassis number < 1
64     try
65     {
66         Chassis chassis{0};
67         ADD_FAILURE() << "Should not have reached this line.";
68     }
69     catch (const std::invalid_argument& e)
70     {
71         EXPECT_STREQ(e.what(), "Invalid chassis number: 0");
72     }
73     catch (...)
74     {
75         ADD_FAILURE() << "Should not have caught exception.";
76     }
77 }
78 
79 TEST(ChassisTests, AddToIDMap)
80 {
81     // Create vector of Device objects
82     std::vector<std::unique_ptr<Device>> devices{};
83     devices.emplace_back(createDevice("reg1", {"rail1"}));
84     devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
85     devices.emplace_back(createDevice("reg3"));
86 
87     // Create Chassis
88     Chassis chassis{1, std::move(devices)};
89 
90     // Add Device and Rail objects within the Chassis to an IDMap
91     IDMap idMap{};
92     chassis.addToIDMap(idMap);
93 
94     // Verify all Devices are in the IDMap
95     EXPECT_NO_THROW(idMap.getDevice("reg1"));
96     EXPECT_NO_THROW(idMap.getDevice("reg2"));
97     EXPECT_NO_THROW(idMap.getDevice("reg3"));
98     EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument);
99 
100     // Verify all Rails are in the IDMap
101     EXPECT_NO_THROW(idMap.getRail("rail1"));
102     EXPECT_NO_THROW(idMap.getRail("rail2a"));
103     EXPECT_NO_THROW(idMap.getRail("rail2b"));
104     EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
105 }
106 
107 TEST(ChassisTests, Configure)
108 {
109     // Test where no devices were specified in constructor
110     {
111         // Create Chassis
112         std::unique_ptr<Chassis> chassis = std::make_unique<Chassis>(1);
113         Chassis* chassisPtr = chassis.get();
114 
115         // Create System that contains Chassis
116         std::vector<std::unique_ptr<Rule>> rules{};
117         std::vector<std::unique_ptr<Chassis>> chassisVec{};
118         chassisVec.emplace_back(std::move(chassis));
119         System system{std::move(rules), std::move(chassisVec)};
120 
121         // Call configure()
122         journal::clear();
123         chassisPtr->configure(system);
124         EXPECT_EQ(journal::getDebugMessages().size(), 0);
125         EXPECT_EQ(journal::getErrMessages().size(), 0);
126         std::vector<std::string> expectedInfoMessages{"Configuring chassis 1"};
127         EXPECT_EQ(journal::getInfoMessages(), expectedInfoMessages);
128     }
129 
130     // Test where devices were specified in constructor
131     {
132         std::vector<std::unique_ptr<Device>> devices{};
133 
134         // Create Device vdd0_reg
135         {
136             // Create Configuration
137             std::vector<std::unique_ptr<Action>> actions{};
138             std::unique_ptr<Configuration> configuration =
139                 std::make_unique<Configuration>(1.3, std::move(actions));
140 
141             // Create Device
142             std::unique_ptr<i2c::I2CInterface> i2cInterface =
143                 createI2CInterface();
144             std::unique_ptr<PresenceDetection> presenceDetection{};
145             std::unique_ptr<Device> device = std::make_unique<Device>(
146                 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg",
147                 std::move(i2cInterface), std::move(presenceDetection),
148                 std::move(configuration));
149             devices.emplace_back(std::move(device));
150         }
151 
152         // Create Device vdd1_reg
153         {
154             // Create Configuration
155             std::vector<std::unique_ptr<Action>> actions{};
156             std::unique_ptr<Configuration> configuration =
157                 std::make_unique<Configuration>(1.2, std::move(actions));
158 
159             // Create Device
160             std::unique_ptr<i2c::I2CInterface> i2cInterface =
161                 createI2CInterface();
162             std::unique_ptr<PresenceDetection> presenceDetection{};
163             std::unique_ptr<Device> device = std::make_unique<Device>(
164                 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg",
165                 std::move(i2cInterface), std::move(presenceDetection),
166                 std::move(configuration));
167             devices.emplace_back(std::move(device));
168         }
169 
170         // Create Chassis
171         std::unique_ptr<Chassis> chassis =
172             std::make_unique<Chassis>(2, std::move(devices));
173         Chassis* chassisPtr = chassis.get();
174 
175         // Create System that contains Chassis
176         std::vector<std::unique_ptr<Rule>> rules{};
177         std::vector<std::unique_ptr<Chassis>> chassisVec{};
178         chassisVec.emplace_back(std::move(chassis));
179         System system{std::move(rules), std::move(chassisVec)};
180 
181         // Call configure()
182         journal::clear();
183         chassisPtr->configure(system);
184         std::vector<std::string> expectedDebugMessages{
185             "Configuring vdd0_reg: volts=1.300000",
186             "Configuring vdd1_reg: volts=1.200000"};
187         EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
188         EXPECT_EQ(journal::getErrMessages().size(), 0);
189         std::vector<std::string> expectedInfoMessages{"Configuring chassis 2"};
190         EXPECT_EQ(journal::getInfoMessages(), expectedInfoMessages);
191     }
192 }
193 
194 TEST(ChassisTests, GetDevices)
195 {
196     // Test where no devices were specified in constructor
197     {
198         Chassis chassis{2};
199         EXPECT_EQ(chassis.getDevices().size(), 0);
200     }
201 
202     // Test where devices were specified in constructor
203     {
204         // Create vector of Device objects
205         std::vector<std::unique_ptr<Device>> devices{};
206         devices.emplace_back(createDevice("vdd_reg1"));
207         devices.emplace_back(createDevice("vdd_reg2"));
208 
209         // Create Chassis
210         Chassis chassis{1, std::move(devices)};
211         EXPECT_EQ(chassis.getDevices().size(), 2);
212         EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
213         EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
214     }
215 }
216 
217 TEST(ChassisTests, GetNumber)
218 {
219     Chassis chassis{3};
220     EXPECT_EQ(chassis.getNumber(), 3);
221 }
222