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.hpp"
17 #include "chassis.hpp"
18 #include "configuration.hpp"
19 #include "device.hpp"
20 #include "i2c_interface.hpp"
21 #include "journal.hpp"
22 #include "mock_action.hpp"
23 #include "mock_journal.hpp"
24 #include "mocked_i2c_interface.hpp"
25 #include "presence_detection.hpp"
26 #include "rail.hpp"
27 #include "rule.hpp"
28 #include "sensor_monitoring.hpp"
29 #include "system.hpp"
30 
31 #include <memory>
32 #include <optional>
33 #include <utility>
34 #include <vector>
35 
36 #include <gmock/gmock.h>
37 #include <gtest/gtest.h>
38 
39 using namespace phosphor::power::regulators;
40 
41 using ::testing::Return;
42 
43 TEST(RailTests, Constructor)
44 {
45     // Test where only required parameters are specified
46     {
47         Rail rail{"vdd0"};
48         EXPECT_EQ(rail.getID(), "vdd0");
49         EXPECT_EQ(rail.getConfiguration(), nullptr);
50         EXPECT_EQ(rail.getSensorMonitoring(), nullptr);
51     }
52 
53     // Test where all parameters are specified
54     {
55         // Create Configuration
56         std::optional<double> volts{1.3};
57         std::vector<std::unique_ptr<Action>> actions{};
58         actions.push_back(std::make_unique<MockAction>());
59         actions.push_back(std::make_unique<MockAction>());
60         std::unique_ptr<Configuration> configuration =
61             std::make_unique<Configuration>(volts, std::move(actions));
62 
63         // Create SensorMonitoring
64         actions.clear();
65         actions.push_back(std::make_unique<MockAction>());
66         std::unique_ptr<SensorMonitoring> sensorMonitoring =
67             std::make_unique<SensorMonitoring>(std::move(actions));
68 
69         // Create Rail
70         Rail rail{"vddr1", std::move(configuration),
71                   std::move(sensorMonitoring)};
72         EXPECT_EQ(rail.getID(), "vddr1");
73         EXPECT_NE(rail.getConfiguration(), nullptr);
74         EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true);
75         EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 1.3);
76         EXPECT_EQ(rail.getConfiguration()->getActions().size(), 2);
77         EXPECT_NE(rail.getSensorMonitoring(), nullptr);
78         EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 1);
79     }
80 }
81 
82 TEST(RailTests, Configure)
83 {
84     // Test where Configuration was not specified in constructor
85     {
86         // Create Rail
87         std::unique_ptr<Rail> rail = std::make_unique<Rail>("vdd0");
88         Rail* railPtr = rail.get();
89 
90         // Create Device that contains Rail
91         std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
92             std::make_unique<i2c::MockedI2CInterface>();
93         std::unique_ptr<PresenceDetection> presenceDetection{};
94         std::unique_ptr<Configuration> deviceConfiguration{};
95         std::vector<std::unique_ptr<Rail>> rails{};
96         rails.emplace_back(std::move(rail));
97         std::unique_ptr<Device> device = std::make_unique<Device>(
98             "reg1", true, "/system/chassis/motherboard/reg1",
99             std::move(i2cInterface), std::move(presenceDetection),
100             std::move(deviceConfiguration), std::move(rails));
101         Device* devicePtr = device.get();
102 
103         // Create Chassis that contains Device
104         std::vector<std::unique_ptr<Device>> devices{};
105         devices.emplace_back(std::move(device));
106         std::unique_ptr<Chassis> chassis =
107             std::make_unique<Chassis>(1, std::move(devices));
108         Chassis* chassisPtr = chassis.get();
109 
110         // Create System that contains Chassis
111         std::vector<std::unique_ptr<Rule>> rules{};
112         std::vector<std::unique_ptr<Chassis>> chassisVec{};
113         chassisVec.emplace_back(std::move(chassis));
114         System system{std::move(rules), std::move(chassisVec)};
115 
116         // Call configure().  Should do nothing.
117         journal::clear();
118         railPtr->configure(system, *chassisPtr, *devicePtr);
119         EXPECT_EQ(journal::getDebugMessages().size(), 0);
120         EXPECT_EQ(journal::getErrMessages().size(), 0);
121     }
122 
123     // Test where Configuration was specified in constructor
124     {
125         // Create Configuration
126         std::optional<double> volts{1.3};
127         std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
128         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
129         std::vector<std::unique_ptr<Action>> actions{};
130         actions.emplace_back(std::move(action));
131         std::unique_ptr<Configuration> configuration =
132             std::make_unique<Configuration>(volts, std::move(actions));
133 
134         // Create Rail
135         std::unique_ptr<Rail> rail =
136             std::make_unique<Rail>("vddr1", std::move(configuration));
137         Rail* railPtr = rail.get();
138 
139         // Create Device that contains Rail
140         std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
141             std::make_unique<i2c::MockedI2CInterface>();
142         std::unique_ptr<PresenceDetection> presenceDetection{};
143         std::unique_ptr<Configuration> deviceConfiguration{};
144         std::vector<std::unique_ptr<Rail>> rails{};
145         rails.emplace_back(std::move(rail));
146         std::unique_ptr<Device> device = std::make_unique<Device>(
147             "reg1", true, "/system/chassis/motherboard/reg1",
148             std::move(i2cInterface), std::move(presenceDetection),
149             std::move(deviceConfiguration), std::move(rails));
150         Device* devicePtr = device.get();
151 
152         // Create Chassis that contains Device
153         std::vector<std::unique_ptr<Device>> devices{};
154         devices.emplace_back(std::move(device));
155         std::unique_ptr<Chassis> chassis =
156             std::make_unique<Chassis>(1, std::move(devices));
157         Chassis* chassisPtr = chassis.get();
158 
159         // Create System that contains Chassis
160         std::vector<std::unique_ptr<Rule>> rules{};
161         std::vector<std::unique_ptr<Chassis>> chassisVec{};
162         chassisVec.emplace_back(std::move(chassis));
163         System system{std::move(rules), std::move(chassisVec)};
164 
165         // Call configure().  Should execute Configuration and log debug message
166         // to journal.
167         journal::clear();
168         railPtr->configure(system, *chassisPtr, *devicePtr);
169         std::vector<std::string> expectedDebugMessages{
170             "Configuring vddr1: volts=1.300000"};
171         EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
172         EXPECT_EQ(journal::getErrMessages().size(), 0);
173     }
174 }
175 
176 TEST(RailTests, GetConfiguration)
177 {
178     // Test where Configuration was not specified in constructor
179     {
180         Rail rail{"vdd0"};
181         EXPECT_EQ(rail.getConfiguration(), nullptr);
182     }
183 
184     // Test where Configuration was specified in constructor
185     {
186         // Create Configuration
187         std::optional<double> volts{3.2};
188         std::vector<std::unique_ptr<Action>> actions{};
189         actions.push_back(std::make_unique<MockAction>());
190         std::unique_ptr<Configuration> configuration =
191             std::make_unique<Configuration>(volts, std::move(actions));
192 
193         // Create Rail
194         Rail rail{"vddr1", std::move(configuration)};
195         EXPECT_NE(rail.getConfiguration(), nullptr);
196         EXPECT_EQ(rail.getConfiguration()->getVolts().has_value(), true);
197         EXPECT_EQ(rail.getConfiguration()->getVolts().value(), 3.2);
198         EXPECT_EQ(rail.getConfiguration()->getActions().size(), 1);
199     }
200 }
201 
202 TEST(RailTests, GetID)
203 {
204     Rail rail{"vio2"};
205     EXPECT_EQ(rail.getID(), "vio2");
206 }
207 
208 TEST(RailTests, GetSensorMonitoring)
209 {
210     // Test where SensorMonitoring was not specified in constructor
211     {
212         Rail rail{"vdd0", nullptr, nullptr};
213         EXPECT_EQ(rail.getSensorMonitoring(), nullptr);
214     }
215 
216     // Test where SensorMonitoring was specified in constructor
217     {
218         std::unique_ptr<Configuration> configuration{};
219 
220         // Create SensorMonitoring
221         std::vector<std::unique_ptr<Action>> actions{};
222         actions.push_back(std::make_unique<MockAction>());
223         actions.push_back(std::make_unique<MockAction>());
224         std::unique_ptr<SensorMonitoring> sensorMonitoring =
225             std::make_unique<SensorMonitoring>(std::move(actions));
226 
227         // Create Rail
228         Rail rail{"vddr1", std::move(configuration),
229                   std::move(sensorMonitoring)};
230         EXPECT_NE(rail.getSensorMonitoring(), nullptr);
231         EXPECT_EQ(rail.getSensorMonitoring()->getActions().size(), 2);
232     }
233 }
234