blob: 4d31e4ee5154e4f7d72f433828f83f58083ac37b [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>(
Bob Kinga76898f2020-10-13 15:08:33 +0800105 "reg1", true,
106 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King833b8e02020-06-11 14:56:38 +0800107 std::move(i2cInterface), std::move(presenceDetection),
108 std::move(deviceConfiguration), std::move(rails));
109 Device* devicePtr = device.get();
110
111 // Create Chassis that contains Device
112 std::vector<std::unique_ptr<Device>> devices{};
113 devices.emplace_back(std::move(device));
114 std::unique_ptr<Chassis> chassis =
115 std::make_unique<Chassis>(1, std::move(devices));
116 Chassis* chassisPtr = chassis.get();
117
118 // Create System that contains Chassis
119 std::vector<std::unique_ptr<Rule>> rules{};
120 std::vector<std::unique_ptr<Chassis>> chassisVec{};
121 chassisVec.emplace_back(std::move(chassis));
122 System system{std::move(rules), std::move(chassisVec)};
123
124 // Execute sensorMonitoring
Bob King8a552922020-08-05 17:02:31 +0800125 sensorMonitoringPtr->execute(services, system, *chassisPtr, *devicePtr,
126 *railPtr);
Bob King833b8e02020-06-11 14:56:38 +0800127 }
128
129 // Test where fails
130 {
Bob King8a552922020-08-05 17:02:31 +0800131 // Create mock services. Expect logError() to be called.
132 MockServices services{};
133 MockJournal& journal = services.getMockJournal();
134 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
135 std::vector<std::string> expectedErrMessagesException{
136 "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
137 "ActionError: pmbus_read_sensor: { type: iout, command: 0x8C, "
138 "format: linear_11 }"};
139
140 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
141 EXPECT_CALL(journal,
142 logError("Unable to monitor sensors for rail vio2"))
143 .Times(1);
144
Bob King833b8e02020-06-11 14:56:38 +0800145 // Create PMBusReadSensorAction
146 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
147 uint8_t command = 0x8C;
148 pmbus_utils::SensorDataFormat format{
149 pmbus_utils::SensorDataFormat::linear_11};
150 std::optional<int8_t> exponent{};
151 std::unique_ptr<PMBusReadSensorAction> action =
152 std::make_unique<PMBusReadSensorAction>(type, command, format,
153 exponent);
154
155 // Create mock I2CInterface.
156 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
157 std::make_unique<i2c::MockedI2CInterface>();
158 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
159 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
160 .Times(1)
161 .WillOnce(Throw(
162 i2c::I2CException{"Failed to write byte", "/dev/i2c-1", 0x70}));
163
164 // Create SensorMonitoring
165 std::vector<std::unique_ptr<Action>> actions{};
166 actions.emplace_back(std::move(action));
167 std::unique_ptr<SensorMonitoring> sensorMonitoring =
168 std::make_unique<SensorMonitoring>(std::move(actions));
169 SensorMonitoring* sensorMonitoringPtr = sensorMonitoring.get();
170
171 // Create Rail that contains sensorMonitoring
172 std::unique_ptr<Configuration> configuration{};
173 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
174 "vio2", std::move(configuration), std::move(sensorMonitoring));
175 Rail* railPtr = rail.get();
176
177 // Create Device that contains Rail
178 std::unique_ptr<PresenceDetection> presenceDetection{};
179 std::unique_ptr<Configuration> deviceConfiguration{};
180 std::vector<std::unique_ptr<Rail>> rails{};
181 rails.emplace_back(std::move(rail));
182 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800183 "reg1", true,
184 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King833b8e02020-06-11 14:56:38 +0800185 std::move(i2cInterface), std::move(presenceDetection),
186 std::move(deviceConfiguration), std::move(rails));
187 Device* devicePtr = device.get();
188
189 // Create Chassis that contains Device
190 std::vector<std::unique_ptr<Device>> devices{};
191 devices.emplace_back(std::move(device));
192 std::unique_ptr<Chassis> chassis =
193 std::make_unique<Chassis>(1, std::move(devices));
194 Chassis* chassisPtr = chassis.get();
195
196 // Create System that contains Chassis
197 std::vector<std::unique_ptr<Rule>> rules{};
198 std::vector<std::unique_ptr<Chassis>> chassisVec{};
199 chassisVec.emplace_back(std::move(chassis));
200 System system{std::move(rules), std::move(chassisVec)};
201
202 // Execute sensorMonitoring
Bob King8a552922020-08-05 17:02:31 +0800203 sensorMonitoringPtr->execute(services, system, *chassisPtr, *devicePtr,
204 *railPtr);
Bob King833b8e02020-06-11 14:56:38 +0800205 }
Shawn McCarneybc47c1b2020-03-10 15:38:07 -0500206}
207
208TEST(SensorMonitoringTests, GetActions)
209{
210 std::vector<std::unique_ptr<Action>> actions{};
211
212 MockAction* action1 = new MockAction{};
213 actions.push_back(std::unique_ptr<MockAction>{action1});
214
215 MockAction* action2 = new MockAction{};
216 actions.push_back(std::unique_ptr<MockAction>{action2});
217
218 SensorMonitoring sensorMonitoring(std::move(actions));
219 EXPECT_EQ(sensorMonitoring.getActions().size(), 2);
220 EXPECT_EQ(sensorMonitoring.getActions()[0].get(), action1);
221 EXPECT_EQ(sensorMonitoring.getActions()[1].get(), action2);
222}