blob: 8f111eb362a45cf42c92a69acd25b736d85ebdf6 [file] [log] [blame]
Shawn McCarneybc47c1b2020-03-10 15:38:07 -05001/**
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"
Bob King833b8e02020-06-11 14:56:38 +080017#include "chassis.hpp"
18#include "configuration.hpp"
19#include "device.hpp"
20#include "i2c_interface.hpp"
Shawn McCarneybc47c1b2020-03-10 15:38:07 -050021#include "mock_action.hpp"
Bob King833b8e02020-06-11 14:56:38 +080022#include "mock_journal.hpp"
Bob King8a552922020-08-05 17:02:31 +080023#include "mock_services.hpp"
Bob King833b8e02020-06-11 14:56:38 +080024#include "mocked_i2c_interface.hpp"
25#include "pmbus_read_sensor_action.hpp"
26#include "pmbus_utils.hpp"
27#include "presence_detection.hpp"
28#include "rail.hpp"
29#include "rule.hpp"
Shawn McCarneybc47c1b2020-03-10 15:38:07 -050030#include "sensor_monitoring.hpp"
Bob King833b8e02020-06-11 14:56:38 +080031#include "system.hpp"
Shawn McCarneybc47c1b2020-03-10 15:38:07 -050032
Bob King833b8e02020-06-11 14:56:38 +080033#include <cstdint>
Shawn McCarneybc47c1b2020-03-10 15:38:07 -050034#include <memory>
Bob King833b8e02020-06-11 14:56:38 +080035#include <optional>
Shawn McCarneybc47c1b2020-03-10 15:38:07 -050036#include <utility>
37#include <vector>
38
Bob King833b8e02020-06-11 14:56:38 +080039#include <gmock/gmock.h>
Shawn McCarneybc47c1b2020-03-10 15:38:07 -050040#include <gtest/gtest.h>
41
42using namespace phosphor::power::regulators;
Bob King833b8e02020-06-11 14:56:38 +080043using namespace phosphor::power::regulators::pmbus_utils;
44
45using ::testing::A;
46using ::testing::Return;
47using ::testing::Throw;
48using ::testing::TypedEq;
Shawn McCarneybc47c1b2020-03-10 15:38:07 -050049
50TEST(SensorMonitoringTests, Constructor)
51{
52 std::vector<std::unique_ptr<Action>> actions{};
53 actions.push_back(std::make_unique<MockAction>());
54
55 SensorMonitoring sensorMonitoring(std::move(actions));
56 EXPECT_EQ(sensorMonitoring.getActions().size(), 1);
57}
58
59TEST(SensorMonitoringTests, Execute)
60{
Bob King833b8e02020-06-11 14:56:38 +080061 // Test where works
62 {
Bob King8a552922020-08-05 17:02:31 +080063 // Create mock services. No logging should occur.
64 MockServices services{};
65 MockJournal& journal = services.getMockJournal();
66 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
67 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
68
Bob King833b8e02020-06-11 14:56:38 +080069 // Create PMBusReadSensorAction
70 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
71 uint8_t command = 0x8C;
72 pmbus_utils::SensorDataFormat format{
73 pmbus_utils::SensorDataFormat::linear_11};
74 std::optional<int8_t> exponent{};
75 std::unique_ptr<PMBusReadSensorAction> action =
76 std::make_unique<PMBusReadSensorAction>(type, command, format,
77 exponent);
78
79 // Create mock I2CInterface.
80 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
81 std::make_unique<i2c::MockedI2CInterface>();
82 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
83 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
84 .Times(1);
85
86 // Create SensorMonitoring
87 std::vector<std::unique_ptr<Action>> actions{};
88 actions.emplace_back(std::move(action));
89 std::unique_ptr<SensorMonitoring> sensorMonitoring =
90 std::make_unique<SensorMonitoring>(std::move(actions));
91 SensorMonitoring* sensorMonitoringPtr = sensorMonitoring.get();
92
93 // Create Rail that contains sensorMonitoring
94 std::unique_ptr<Configuration> configuration{};
95 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
96 "vio2", std::move(configuration), std::move(sensorMonitoring));
97 Rail* railPtr = rail.get();
98
99 // Create Device that contains Rail
100 std::unique_ptr<PresenceDetection> presenceDetection{};
101 std::unique_ptr<Configuration> deviceConfiguration{};
102 std::vector<std::unique_ptr<Rail>> rails{};
103 rails.emplace_back(std::move(rail));
104 std::unique_ptr<Device> device = std::make_unique<Device>(
105 "reg1", true, "/system/chassis/motherboard/reg1",
106 std::move(i2cInterface), std::move(presenceDetection),
107 std::move(deviceConfiguration), std::move(rails));
108 Device* devicePtr = device.get();
109
110 // Create Chassis that contains Device
111 std::vector<std::unique_ptr<Device>> devices{};
112 devices.emplace_back(std::move(device));
113 std::unique_ptr<Chassis> chassis =
114 std::make_unique<Chassis>(1, std::move(devices));
115 Chassis* chassisPtr = chassis.get();
116
117 // Create System that contains Chassis
118 std::vector<std::unique_ptr<Rule>> rules{};
119 std::vector<std::unique_ptr<Chassis>> chassisVec{};
120 chassisVec.emplace_back(std::move(chassis));
121 System system{std::move(rules), std::move(chassisVec)};
122
123 // Execute sensorMonitoring
Bob King8a552922020-08-05 17:02:31 +0800124 sensorMonitoringPtr->execute(services, system, *chassisPtr, *devicePtr,
125 *railPtr);
Bob King833b8e02020-06-11 14:56:38 +0800126 }
127
128 // Test where fails
129 {
Bob King8a552922020-08-05 17:02:31 +0800130 // Create mock services. Expect logError() to be called.
131 MockServices services{};
132 MockJournal& journal = services.getMockJournal();
133 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
134 std::vector<std::string> expectedErrMessagesException{
135 "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
136 "ActionError: pmbus_read_sensor: { type: iout, command: 0x8C, "
137 "format: linear_11 }"};
138
139 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
140 EXPECT_CALL(journal,
141 logError("Unable to monitor sensors for rail vio2"))
142 .Times(1);
143
Bob King833b8e02020-06-11 14:56:38 +0800144 // Create PMBusReadSensorAction
145 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
146 uint8_t command = 0x8C;
147 pmbus_utils::SensorDataFormat format{
148 pmbus_utils::SensorDataFormat::linear_11};
149 std::optional<int8_t> exponent{};
150 std::unique_ptr<PMBusReadSensorAction> action =
151 std::make_unique<PMBusReadSensorAction>(type, command, format,
152 exponent);
153
154 // Create mock I2CInterface.
155 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
156 std::make_unique<i2c::MockedI2CInterface>();
157 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
158 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
159 .Times(1)
160 .WillOnce(Throw(
161 i2c::I2CException{"Failed to write byte", "/dev/i2c-1", 0x70}));
162
163 // Create SensorMonitoring
164 std::vector<std::unique_ptr<Action>> actions{};
165 actions.emplace_back(std::move(action));
166 std::unique_ptr<SensorMonitoring> sensorMonitoring =
167 std::make_unique<SensorMonitoring>(std::move(actions));
168 SensorMonitoring* sensorMonitoringPtr = sensorMonitoring.get();
169
170 // Create Rail that contains sensorMonitoring
171 std::unique_ptr<Configuration> configuration{};
172 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
173 "vio2", std::move(configuration), std::move(sensorMonitoring));
174 Rail* railPtr = rail.get();
175
176 // Create Device that contains Rail
177 std::unique_ptr<PresenceDetection> presenceDetection{};
178 std::unique_ptr<Configuration> deviceConfiguration{};
179 std::vector<std::unique_ptr<Rail>> rails{};
180 rails.emplace_back(std::move(rail));
181 std::unique_ptr<Device> device = std::make_unique<Device>(
182 "reg1", true, "/system/chassis/motherboard/reg1",
183 std::move(i2cInterface), std::move(presenceDetection),
184 std::move(deviceConfiguration), std::move(rails));
185 Device* devicePtr = device.get();
186
187 // Create Chassis that contains Device
188 std::vector<std::unique_ptr<Device>> devices{};
189 devices.emplace_back(std::move(device));
190 std::unique_ptr<Chassis> chassis =
191 std::make_unique<Chassis>(1, std::move(devices));
192 Chassis* chassisPtr = chassis.get();
193
194 // Create System that contains Chassis
195 std::vector<std::unique_ptr<Rule>> rules{};
196 std::vector<std::unique_ptr<Chassis>> chassisVec{};
197 chassisVec.emplace_back(std::move(chassis));
198 System system{std::move(rules), std::move(chassisVec)};
199
200 // Execute sensorMonitoring
Bob King8a552922020-08-05 17:02:31 +0800201 sensorMonitoringPtr->execute(services, system, *chassisPtr, *devicePtr,
202 *railPtr);
Bob King833b8e02020-06-11 14:56:38 +0800203 }
Shawn McCarneybc47c1b2020-03-10 15:38:07 -0500204}
205
206TEST(SensorMonitoringTests, GetActions)
207{
208 std::vector<std::unique_ptr<Action>> actions{};
209
210 MockAction* action1 = new MockAction{};
211 actions.push_back(std::unique_ptr<MockAction>{action1});
212
213 MockAction* action2 = new MockAction{};
214 actions.push_back(std::unique_ptr<MockAction>{action2});
215
216 SensorMonitoring sensorMonitoring(std::move(actions));
217 EXPECT_EQ(sensorMonitoring.getActions().size(), 2);
218 EXPECT_EQ(sensorMonitoring.getActions()[0].get(), action1);
219 EXPECT_EQ(sensorMonitoring.getActions()[1].get(), action2);
220}