blob: ea8ac91966072f622c726e9397818a914df7c7af [file] [log] [blame]
James Zheng6df8bb52024-11-27 23:38:47 +00001#include "failsafeloggers/builder.hpp"
2#include "failsafeloggers/failsafe_logger.hpp"
3#include "failsafeloggers/failsafe_logger_utility.hpp"
Josh Lehande745422020-11-07 02:14:09 -08004#include "pid/ec/logging.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07005#include "pid/ec/pid.hpp"
Patrick Venturea58197c2018-06-11 15:29:45 -07006#include "pid/zone.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07007#include "sensors/manager.hpp"
8#include "test/controller_mock.hpp"
9#include "test/helpers.hpp"
10#include "test/sensor_mock.hpp"
Patrick Venturea58197c2018-06-11 15:29:45 -070011
Patrick Venturea83a3ec2020-08-04 09:52:05 -070012#include <sdbusplus/test/sdbus_mock.hpp>
13
Patrick Venturea58197c2018-06-11 15:29:45 -070014#include <chrono>
15#include <cstring>
James Zheng6df8bb52024-11-27 23:38:47 +000016#include <unordered_map>
Patrick Venturea58197c2018-06-11 15:29:45 -070017#include <vector>
18
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070019#include <gmock/gmock.h>
20#include <gtest/gtest.h>
Patrick Venturea58197c2018-06-11 15:29:45 -070021
Patrick Venturea0764872020-08-08 07:48:43 -070022namespace pid_control
23{
24namespace
25{
26
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070027using ::testing::_;
Patrick Venturea58197c2018-06-11 15:29:45 -070028using ::testing::IsNull;
29using ::testing::Return;
30using ::testing::StrEq;
Patrick Venturea58197c2018-06-11 15:29:45 -070031
32static std::string modeInterface = "xyz.openbmc_project.Control.Mode";
Harvey Wucc0232a2023-02-09 14:58:55 +080033static std::string debugZoneInterface = "xyz.openbmc_project.Debug.Pid.Zone";
ykchiu7c6d35d2023-05-10 17:01:46 +080034static std::string enableInterface = "xyz.openbmc_project.Object.Enable";
Harvey Wu37180062023-10-02 09:42:50 +080035static std::string debugThermalPowerInterface =
36 "xyz.openbmc_project.Debug.Pid.ThermalPower";
Patrick Venturea58197c2018-06-11 15:29:45 -070037
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070038namespace
39{
Patrick Venturea58197c2018-06-11 15:29:45 -070040
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070041TEST(PidZoneConstructorTest, BoringConstructorTest)
42{
Patrick Venturea58197c2018-06-11 15:29:45 -070043 // Build a PID Zone.
44
ykchiu7c6d35d2023-05-10 17:01:46 +080045 sdbusplus::SdBusMock sdbus_mock_passive, sdbus_mock_host, sdbus_mock_mode,
46 sdbus_mock_enable;
Patrick Venturea58197c2018-06-11 15:29:45 -070047 auto bus_mock_passive = sdbusplus::get_mocked_new(&sdbus_mock_passive);
48 auto bus_mock_host = sdbusplus::get_mocked_new(&sdbus_mock_host);
49 auto bus_mock_mode = sdbusplus::get_mocked_new(&sdbus_mock_mode);
ykchiu7c6d35d2023-05-10 17:01:46 +080050 auto bus_mock_enable = sdbusplus::get_mocked_new(&sdbus_mock_enable);
Patrick Venturea58197c2018-06-11 15:29:45 -070051
52 EXPECT_CALL(sdbus_mock_host,
53 sd_bus_add_object_manager(
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070054 IsNull(), _, StrEq("/xyz/openbmc_project/extsensors")))
Patrick Venturea58197c2018-06-11 15:29:45 -070055 .WillOnce(Return(0));
56
James Feist1fe08952019-05-07 09:17:16 -070057 SensorManager m(bus_mock_passive, bus_mock_host);
Patrick Venturea58197c2018-06-11 15:29:45 -070058
59 bool defer = true;
Delphine CC Chiu97889632023-11-06 11:32:46 +080060 bool accSetPoint = false;
Patrick Venturee2ec0f62018-09-04 12:30:27 -070061 const char* objPath = "/path/";
Patrick Venturea58197c2018-06-11 15:29:45 -070062 int64_t zone = 1;
James Feist3484bed2019-02-25 13:28:18 -080063 double minThermalOutput = 1000.0;
Harvey Wu92f9f3c2023-11-07 09:23:35 +080064 double failSafePercent = 100;
Bonnie Lo0e8fc392022-10-05 10:20:55 +080065 conf::CycleTime cycleTime;
Patrick Venturea58197c2018-06-11 15:29:45 -070066
James Feist0709e2f2020-07-08 10:59:45 -070067 double d;
Patrick Venturea58197c2018-06-11 15:29:45 -070068 std::vector<std::string> properties;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070069 SetupDbusObject(&sdbus_mock_mode, defer, objPath, modeInterface, properties,
James Feist0709e2f2020-07-08 10:59:45 -070070 &d);
Harvey Wucc0232a2023-02-09 14:58:55 +080071 SetupDbusObject(&sdbus_mock_mode, defer, objPath, debugZoneInterface,
72 properties, &d);
Patrick Venturea58197c2018-06-11 15:29:45 -070073
ykchiu7c6d35d2023-05-10 17:01:46 +080074 std::string sensorname = "temp1";
Patrick Williamsbd63bca2024-08-16 15:21:10 -040075 std::string pidsensorpath =
76 "/xyz/openbmc_project/settings/fanctrl/zone1/" + sensorname;
ykchiu7c6d35d2023-05-10 17:01:46 +080077
78 double de;
79 std::vector<std::string> propertiesenable;
80 SetupDbusObject(&sdbus_mock_enable, defer, pidsensorpath.c_str(),
81 enableInterface, propertiesenable, &de);
82
Bonnie Lo0e8fc392022-10-05 10:20:55 +080083 DbusPidZone p(zone, minThermalOutput, failSafePercent, cycleTime, m,
Delphine CC Chiu97889632023-11-06 11:32:46 +080084 bus_mock_mode, objPath, defer, accSetPoint);
Patrick Venturea58197c2018-06-11 15:29:45 -070085 // Success.
86}
87
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070088} // namespace
Patrick Venturea58197c2018-06-11 15:29:45 -070089
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070090class PidZoneTest : public ::testing::Test
91{
92 protected:
93 PidZoneTest() :
94 property_index(), properties(), sdbus_mock_passive(), sdbus_mock_host(),
ykchiu7c6d35d2023-05-10 17:01:46 +080095 sdbus_mock_mode(), sdbus_mock_enable()
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070096 {
97 EXPECT_CALL(sdbus_mock_host,
98 sd_bus_add_object_manager(
99 IsNull(), _, StrEq("/xyz/openbmc_project/extsensors")))
100 .WillOnce(Return(0));
Patrick Venturea58197c2018-06-11 15:29:45 -0700101
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700102 auto bus_mock_passive = sdbusplus::get_mocked_new(&sdbus_mock_passive);
103 auto bus_mock_host = sdbusplus::get_mocked_new(&sdbus_mock_host);
104 auto bus_mock_mode = sdbusplus::get_mocked_new(&sdbus_mock_mode);
ykchiu7c6d35d2023-05-10 17:01:46 +0800105 auto bus_mock_enable = sdbusplus::get_mocked_new(&sdbus_mock_enable);
Patrick Venturea58197c2018-06-11 15:29:45 -0700106
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700107 // Compiler weirdly not happy about just instantiating mgr(...);
James Feist1fe08952019-05-07 09:17:16 -0700108 SensorManager m(bus_mock_passive, bus_mock_host);
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700109 mgr = std::move(m);
Patrick Venturea58197c2018-06-11 15:29:45 -0700110
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700111 SetupDbusObject(&sdbus_mock_mode, defer, objPath, modeInterface,
112 properties, &property_index);
Harvey Wucc0232a2023-02-09 14:58:55 +0800113 SetupDbusObject(&sdbus_mock_mode, defer, objPath, debugZoneInterface,
114 properties, &property_index);
Patrick Venturea58197c2018-06-11 15:29:45 -0700115
ykchiu7c6d35d2023-05-10 17:01:46 +0800116 SetupDbusObject(&sdbus_mock_enable, defer, pidsensorpath.c_str(),
117 enableInterface, propertiesenable,
118 &propertyenable_index);
119
Delphine CC Chiu97889632023-11-06 11:32:46 +0800120 zone = std::make_unique<DbusPidZone>(
121 zoneId, minThermalOutput, failSafePercent, cycleTime, mgr,
122 bus_mock_mode, objPath, defer, accSetPoint);
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700123 }
Patrick Venturea58197c2018-06-11 15:29:45 -0700124
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700125 // unused
James Feist0709e2f2020-07-08 10:59:45 -0700126 double property_index;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700127 std::vector<std::string> properties;
ykchiu7c6d35d2023-05-10 17:01:46 +0800128 double propertyenable_index;
129 std::vector<std::string> propertiesenable;
Patrick Venturea58197c2018-06-11 15:29:45 -0700130
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700131 sdbusplus::SdBusMock sdbus_mock_passive;
132 sdbusplus::SdBusMock sdbus_mock_host;
133 sdbusplus::SdBusMock sdbus_mock_mode;
ykchiu7c6d35d2023-05-10 17:01:46 +0800134 sdbusplus::SdBusMock sdbus_mock_enable;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700135 int64_t zoneId = 1;
James Feist3484bed2019-02-25 13:28:18 -0800136 double minThermalOutput = 1000.0;
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800137 double failSafePercent = 100;
Harvey Wu37180062023-10-02 09:42:50 +0800138 double setpoint = 50.0;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700139 bool defer = true;
Delphine CC Chiu97889632023-11-06 11:32:46 +0800140 bool accSetPoint = false;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700141 const char* objPath = "/path/";
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700142 SensorManager mgr;
Bonnie Lo0e8fc392022-10-05 10:20:55 +0800143 conf::CycleTime cycleTime;
Patrick Venturea58197c2018-06-11 15:29:45 -0700144
ykchiu7c6d35d2023-05-10 17:01:46 +0800145 std::string sensorname = "temp1";
Harvey Wu37180062023-10-02 09:42:50 +0800146 std::string sensorType = "temp";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400147 std::string pidsensorpath =
148 "/xyz/openbmc_project/settings/fanctrl/zone1/" + sensorname;
ykchiu7c6d35d2023-05-10 17:01:46 +0800149
Patrick Venture597ebd62020-08-11 08:48:19 -0700150 std::unique_ptr<DbusPidZone> zone;
Patrick Venturea58197c2018-06-11 15:29:45 -0700151};
152
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700153TEST_F(PidZoneTest, GetZoneId_ReturnsExpected)
154{
Patrick Venturea58197c2018-06-11 15:29:45 -0700155 // Verifies the zoneId returned is what we expect.
156
Patrick Venture0bbeaf82018-10-30 18:50:31 -0700157 EXPECT_EQ(zoneId, zone->getZoneID());
Patrick Venturea58197c2018-06-11 15:29:45 -0700158}
159
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700160TEST_F(PidZoneTest, GetAndSetManualModeTest_BehavesAsExpected)
161{
Patrick Venturea58197c2018-06-11 15:29:45 -0700162 // Verifies that the zone starts in manual mode. Verifies that one can set
163 // the mode.
164 EXPECT_FALSE(zone->getManualMode());
165
166 zone->setManualMode(true);
167 EXPECT_TRUE(zone->getManualMode());
168}
169
ykchiu7c6d35d2023-05-10 17:01:46 +0800170TEST_F(PidZoneTest, AddPidControlProcessGetAndSetEnableTest_BehavesAsExpected)
171{
172 // Verifies that the zone starts in enable mode. Verifies that one can set
173 // enable the mode.
174 auto bus_mock_enable = sdbusplus::get_mocked_new(&sdbus_mock_enable);
175
176 EXPECT_CALL(sdbus_mock_mode, sd_bus_emit_properties_changed_strv(
177 IsNull(), StrEq(pidsensorpath.c_str()),
178 StrEq(enableInterface), NotNull()))
179 .Times(::testing::AnyNumber())
180 .WillOnce(Invoke(
181 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
182 [[maybe_unused]] const char* interface, const char** names) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400183 EXPECT_STREQ("Enable", names[0]);
184 return 0;
185 }));
ykchiu7c6d35d2023-05-10 17:01:46 +0800186
Harvey Wu37180062023-10-02 09:42:50 +0800187 zone->addPidControlProcess(sensorname, sensorType, setpoint,
188 bus_mock_enable, pidsensorpath.c_str(), defer);
ykchiu7c6d35d2023-05-10 17:01:46 +0800189 EXPECT_TRUE(zone->isPidProcessEnabled(sensorname));
190}
191
Josh Lehana4146eb2020-10-01 11:49:09 -0700192TEST_F(PidZoneTest, SetManualMode_RedundantWritesEnabledOnceAfterManualMode)
193{
194 // Tests adding a fan PID controller to the zone, and verifies it's
195 // touched during processing.
196
197 std::unique_ptr<PIDController> tpid =
198 std::make_unique<ControllerMock>("fan1", zone.get());
199 ControllerMock* tmock = reinterpret_cast<ControllerMock*>(tpid.get());
200
201 // Access the internal pid configuration to clear it out (unrelated to the
202 // test).
Harvey Wu1b3b7302024-10-04 16:49:46 +0800203 [[maybe_unused]] ec::pid_info_t* info = tpid->getPIDInfo();
Josh Lehana4146eb2020-10-01 11:49:09 -0700204
205 zone->addFanPID(std::move(tpid));
206
207 EXPECT_CALL(*tmock, setptProc()).WillOnce(Return(10.0));
208 EXPECT_CALL(*tmock, inputProc()).WillOnce(Return(11.0));
209 EXPECT_CALL(*tmock, outputProc(_));
210
211 // while zone is in auto mode redundant writes should be disabled
212 EXPECT_FALSE(zone->getRedundantWrite());
213
214 // but switching from manual to auto enables a single redundant write
215 zone->setManualMode(true);
216 zone->setManualMode(false);
217 EXPECT_TRUE(zone->getRedundantWrite());
218
219 // after one iteration of a pid loop redundant write should be cleared
220 zone->processFans();
221 EXPECT_FALSE(zone->getRedundantWrite());
222}
223
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700224TEST_F(PidZoneTest, RpmSetPoints_AddMaxClear_BehaveAsExpected)
225{
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700226 // Tests addSetPoint, clearSetPoints, determineMaxSetPointRequest
Nirav Shahccc8bb62022-02-17 21:06:51 -0800227 // and getMinThermalSetPoint.
Patrick Venturea58197c2018-06-11 15:29:45 -0700228
ykchiu7c6d35d2023-05-10 17:01:46 +0800229 // Need to add pid control process for the zone that can enable
230 // the process and add the set point.
231 auto bus_mock_enable = sdbusplus::get_mocked_new(&sdbus_mock_enable);
232
233 EXPECT_CALL(sdbus_mock_mode, sd_bus_emit_properties_changed_strv(
234 IsNull(), StrEq(pidsensorpath.c_str()),
235 StrEq(enableInterface), NotNull()))
236 .Times(::testing::AnyNumber())
237 .WillOnce(Invoke(
238 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
239 [[maybe_unused]] const char* interface, const char** names) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400240 EXPECT_STREQ("Enable", names[0]);
241 return 0;
242 }));
ykchiu7c6d35d2023-05-10 17:01:46 +0800243
Harvey Wu37180062023-10-02 09:42:50 +0800244 zone->addPidControlProcess(sensorname, sensorType, setpoint,
245 bus_mock_enable, pidsensorpath.c_str(), defer);
ykchiu7c6d35d2023-05-10 17:01:46 +0800246
Patrick Venturea58197c2018-06-11 15:29:45 -0700247 // At least one value must be above the minimum thermal setpoint used in
248 // the constructor otherwise it'll choose that value
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800249 std::vector<double> values = {100, 200, 300, 400, 500, 5000};
ykchiu7c6d35d2023-05-10 17:01:46 +0800250
Patrick Venturea58197c2018-06-11 15:29:45 -0700251 for (auto v : values)
252 {
ykchiu7c6d35d2023-05-10 17:01:46 +0800253 zone->addSetPoint(v, sensorname);
Patrick Venturea58197c2018-06-11 15:29:45 -0700254 }
255
256 // This will pull the maximum RPM setpoint request.
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700257 zone->determineMaxSetPointRequest();
258 EXPECT_EQ(5000, zone->getMaxSetPointRequest());
Patrick Venturea58197c2018-06-11 15:29:45 -0700259
260 // Clear the values, so it'll choose the minimum thermal setpoint.
Patrick Venture9bbf3332019-07-16 10:50:37 -0700261 zone->clearSetPoints();
Patrick Venturea58197c2018-06-11 15:29:45 -0700262
263 // This will go through the RPM set point values and grab the maximum.
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700264 zone->determineMaxSetPointRequest();
Nirav Shahccc8bb62022-02-17 21:06:51 -0800265 EXPECT_EQ(zone->getMinThermalSetPoint(), zone->getMaxSetPointRequest());
Patrick Venturea58197c2018-06-11 15:29:45 -0700266}
267
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700268TEST_F(PidZoneTest, RpmSetPoints_AddBelowMinimum_BehavesAsExpected)
269{
Patrick Venturea58197c2018-06-11 15:29:45 -0700270 // Tests adding several RPM setpoints, however, they're all lower than the
Patrick Venture7280e272019-02-11 10:45:32 -0800271 // configured minimal thermal setpoint RPM value.
Patrick Venturea58197c2018-06-11 15:29:45 -0700272
ykchiu7c6d35d2023-05-10 17:01:46 +0800273 // Need to add pid control process for the zone that can enable
274 // the process and add the set point.
275 auto bus_mock_enable = sdbusplus::get_mocked_new(&sdbus_mock_enable);
276
277 EXPECT_CALL(sdbus_mock_mode, sd_bus_emit_properties_changed_strv(
278 IsNull(), StrEq(pidsensorpath.c_str()),
279 StrEq(enableInterface), NotNull()))
280 .Times(::testing::AnyNumber())
281 .WillOnce(Invoke(
282 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
283 [[maybe_unused]] const char* interface, const char** names) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400284 EXPECT_STREQ("Enable", names[0]);
285 return 0;
286 }));
ykchiu7c6d35d2023-05-10 17:01:46 +0800287
Harvey Wu37180062023-10-02 09:42:50 +0800288 zone->addPidControlProcess(sensorname, sensorType, setpoint,
289 bus_mock_enable, pidsensorpath.c_str(), defer);
ykchiu7c6d35d2023-05-10 17:01:46 +0800290
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800291 std::vector<double> values = {100, 200, 300, 400, 500};
ykchiu7c6d35d2023-05-10 17:01:46 +0800292
Patrick Venturea58197c2018-06-11 15:29:45 -0700293 for (auto v : values)
294 {
ykchiu7c6d35d2023-05-10 17:01:46 +0800295 zone->addSetPoint(v, sensorname);
Patrick Venturea58197c2018-06-11 15:29:45 -0700296 }
297
298 // This will pull the maximum RPM setpoint request.
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700299 zone->determineMaxSetPointRequest();
Patrick Venturea58197c2018-06-11 15:29:45 -0700300
301 // Verifies the value returned in the minimal thermal rpm set point.
Nirav Shahccc8bb62022-02-17 21:06:51 -0800302 EXPECT_EQ(zone->getMinThermalSetPoint(), zone->getMaxSetPointRequest());
Patrick Venturea58197c2018-06-11 15:29:45 -0700303}
304
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800305TEST_F(PidZoneTest, GetFailSafePercent_SingleFailedReturnsExpected)
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700306{
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800307 // Tests when only one sensor failed and the sensor's failsafe duty is zero,
308 // and verify that the sensor name is empty and failsafe duty is PID zone's
309 // failsafe duty.
ykchiu9fe3a3c2023-05-11 13:43:54 +0800310
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800311 std::vector<std::string> input1 = {"temp1"};
312 std::vector<std::string> input2 = {"temp2"};
313 std::vector<std::string> input3 = {"temp3"};
ykchiu9fe3a3c2023-05-11 13:43:54 +0800314 std::vector<double> values = {0, 0, 0};
ykchiu9fe3a3c2023-05-11 13:43:54 +0800315
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800316 zone->addPidFailSafePercent(input1, values[0]);
317 zone->addPidFailSafePercent(input2, values[1]);
318 zone->addPidFailSafePercent(input3, values[2]);
ykchiu9fe3a3c2023-05-11 13:43:54 +0800319
Harvey Wua4270072024-05-29 16:11:13 +0800320 zone->markSensorMissing("temp1", "Sensor threshold asserted");
ykchiu9fe3a3c2023-05-11 13:43:54 +0800321
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800322 EXPECT_EQ(failSafePercent, zone->getFailSafePercent());
Harvey Wua4270072024-05-29 16:11:13 +0800323
324 std::map<std::string, std::pair<std::string, double>> failSensorList =
325 zone->getFailSafeSensors();
326 EXPECT_EQ(1, failSensorList.size());
327 EXPECT_EQ("Sensor threshold asserted", failSensorList["temp1"].first);
328 EXPECT_EQ(failSafePercent, failSensorList["temp1"].second);
ykchiu9fe3a3c2023-05-11 13:43:54 +0800329}
330
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800331TEST_F(PidZoneTest, GetFailSafePercent_MultiFailedReturnsExpected)
ykchiu9fe3a3c2023-05-11 13:43:54 +0800332{
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800333 // Tests when multi sensor failed, and verify the final failsafe's sensor
334 // name and duty as expected.
ykchiu9fe3a3c2023-05-11 13:43:54 +0800335
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800336 std::vector<std::string> input1 = {"temp1"};
337 std::vector<std::string> input2 = {"temp2"};
338 std::vector<std::string> input3 = {"temp3"};
ykchiu9fe3a3c2023-05-11 13:43:54 +0800339 std::vector<double> values = {60, 80, 70};
ykchiu9fe3a3c2023-05-11 13:43:54 +0800340
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800341 zone->addPidFailSafePercent(input1, values[0]);
342 zone->addPidFailSafePercent(input2, values[1]);
343 zone->addPidFailSafePercent(input3, values[2]);
ykchiu9fe3a3c2023-05-11 13:43:54 +0800344
Harvey Wua4270072024-05-29 16:11:13 +0800345 zone->markSensorMissing("temp1", "Sensor threshold asserted");
346 zone->markSensorMissing("temp2", "Sensor reading bad");
347 zone->markSensorMissing("temp3", "Sensor unavailable");
ykchiu9fe3a3c2023-05-11 13:43:54 +0800348
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800349 EXPECT_EQ(80, zone->getFailSafePercent());
Harvey Wua4270072024-05-29 16:11:13 +0800350
351 std::map<std::string, std::pair<std::string, double>> failSensorList =
352 zone->getFailSafeSensors();
353 EXPECT_EQ(3, failSensorList.size());
354 EXPECT_EQ("Sensor threshold asserted", failSensorList["temp1"].first);
355 EXPECT_EQ(60, failSensorList["temp1"].second);
356 EXPECT_EQ("Sensor reading bad", failSensorList["temp2"].first);
357 EXPECT_EQ(80, failSensorList["temp2"].second);
358 EXPECT_EQ("Sensor unavailable", failSensorList["temp3"].first);
359 EXPECT_EQ(70, failSensorList["temp3"].second);
Patrick Venturea58197c2018-06-11 15:29:45 -0700360}
361
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700362TEST_F(PidZoneTest, ThermalInputs_FailsafeToValid_ReadsSensors)
363{
Patrick Venturea58197c2018-06-11 15:29:45 -0700364 // This test will add a couple thermal inputs, and verify that the zone
365 // initializes into failsafe mode, and will read each sensor.
366
James Zheng6df8bb52024-11-27 23:38:47 +0000367 // Disable failsafe logger for the unit test.
368 std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> empty_zone_map;
369 buildFailsafeLoggers(empty_zone_map, 0);
370
Patrick Venturea58197c2018-06-11 15:29:45 -0700371 std::string name1 = "temp1";
372 int64_t timeout = 1;
373
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400374 std::unique_ptr<Sensor> sensor1 =
375 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700376 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700377
378 std::string name2 = "temp2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400379 std::unique_ptr<Sensor> sensor2 =
380 std::make_unique<SensorMock>(name2, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700381 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700382
383 std::string type = "unchecked";
384 mgr.addSensor(type, name1, std::move(sensor1));
385 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
386 mgr.addSensor(type, name2, std::move(sensor2));
387 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
388
389 // Now that the sensors exist, add them to the zone.
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800390 zone->addThermalInput(name1, false);
391 zone->addThermalInput(name2, false);
Patrick Venturea58197c2018-06-11 15:29:45 -0700392
393 // Initialize Zone
394 zone->initializeCache();
395
396 // Verify now in failsafe mode.
397 EXPECT_TRUE(zone->getFailSafeMode());
398
399 ReadReturn r1;
400 r1.value = 10.0;
401 r1.updated = std::chrono::high_resolution_clock::now();
402 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
403
404 ReadReturn r2;
405 r2.value = 11.0;
406 r2.updated = std::chrono::high_resolution_clock::now();
407 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
408
409 // Read the sensors, this will put the values into the cache.
410 zone->updateSensors();
411
412 // We should no longer be in failsafe mode.
413 EXPECT_FALSE(zone->getFailSafeMode());
414
415 EXPECT_EQ(r1.value, zone->getCachedValue(name1));
416 EXPECT_EQ(r2.value, zone->getCachedValue(name2));
417}
418
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700419TEST_F(PidZoneTest, FanInputTest_VerifiesFanValuesCached)
420{
Patrick Venturea58197c2018-06-11 15:29:45 -0700421 // This will add a couple fan inputs, and verify the values are cached.
422
James Zheng6df8bb52024-11-27 23:38:47 +0000423 // Disable failsafe logger for the unit test.
424 std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> empty_zone_map;
425 buildFailsafeLoggers(empty_zone_map, 0);
426
Patrick Venturea58197c2018-06-11 15:29:45 -0700427 std::string name1 = "fan1";
428 int64_t timeout = 2;
429
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400430 std::unique_ptr<Sensor> sensor1 =
431 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700432 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700433
434 std::string name2 = "fan2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400435 std::unique_ptr<Sensor> sensor2 =
436 std::make_unique<SensorMock>(name2, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700437 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700438
439 std::string type = "unchecked";
440 mgr.addSensor(type, name1, std::move(sensor1));
441 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
442 mgr.addSensor(type, name2, std::move(sensor2));
443 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
444
445 // Now that the sensors exist, add them to the zone.
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800446 zone->addFanInput(name1, false);
447 zone->addFanInput(name2, false);
Patrick Venturea58197c2018-06-11 15:29:45 -0700448
449 // Initialize Zone
450 zone->initializeCache();
451
452 ReadReturn r1;
453 r1.value = 10.0;
454 r1.updated = std::chrono::high_resolution_clock::now();
455 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
456
457 ReadReturn r2;
458 r2.value = 11.0;
459 r2.updated = std::chrono::high_resolution_clock::now();
460 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
461
462 // Method under test will read through each fan sensor for the zone and
463 // cache the values.
464 zone->updateFanTelemetry();
465
466 EXPECT_EQ(r1.value, zone->getCachedValue(name1));
467 EXPECT_EQ(r2.value, zone->getCachedValue(name2));
468}
469
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700470TEST_F(PidZoneTest, ThermalInput_ValueTimeoutEntersFailSafeMode)
471{
Patrick Venturea58197c2018-06-11 15:29:45 -0700472 // On the second updateSensors call, the updated timestamp will be beyond
473 // the timeout limit.
474
James Zheng6df8bb52024-11-27 23:38:47 +0000475 // Disable failsafe logger for the unit test.
476 std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> empty_zone_map;
477 buildFailsafeLoggers(empty_zone_map, 0);
478
Patrick Venturea58197c2018-06-11 15:29:45 -0700479 int64_t timeout = 1;
480
481 std::string name1 = "temp1";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400482 std::unique_ptr<Sensor> sensor1 =
483 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700484 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700485
486 std::string name2 = "temp2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400487 std::unique_ptr<Sensor> sensor2 =
488 std::make_unique<SensorMock>(name2, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700489 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700490
491 std::string type = "unchecked";
492 mgr.addSensor(type, name1, std::move(sensor1));
493 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
494 mgr.addSensor(type, name2, std::move(sensor2));
495 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
496
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800497 zone->addThermalInput(name1, false);
498 zone->addThermalInput(name2, false);
Patrick Venturea58197c2018-06-11 15:29:45 -0700499
500 // Initialize Zone
501 zone->initializeCache();
502
503 // Verify now in failsafe mode.
504 EXPECT_TRUE(zone->getFailSafeMode());
505
506 ReadReturn r1;
507 r1.value = 10.0;
508 r1.updated = std::chrono::high_resolution_clock::now();
509 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
510
511 ReadReturn r2;
512 r2.value = 11.0;
513 r2.updated = std::chrono::high_resolution_clock::now();
514 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
515
516 zone->updateSensors();
517 EXPECT_FALSE(zone->getFailSafeMode());
518
519 // Ok, so we're not in failsafe mode, so let's set updated to the past.
520 // sensor1 will have an updated field older than its timeout value, but
521 // sensor2 will be fine. :D
522 r1.updated -= std::chrono::seconds(3);
523 r2.updated = std::chrono::high_resolution_clock::now();
524
525 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
526 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
527
528 // Method under test will read each sensor. One sensor's value is older
529 // than the timeout for that sensor and this triggers failsafe mode.
530 zone->updateSensors();
531 EXPECT_TRUE(zone->getFailSafeMode());
532}
533
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800534TEST_F(PidZoneTest, ThermalInput_MissingIsAcceptableNoFailSafe)
535{
536 // This is similar to the above test, but because missingIsAcceptable
537 // is set for sensor1, the zone should not enter failsafe mode when
538 // only sensor1 goes missing.
539 // However, sensor2 going missing should still trigger failsafe mode.
540
James Zheng6df8bb52024-11-27 23:38:47 +0000541 // Disable failsafe logger for the unit test.
542 std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> empty_zone_map;
543 buildFailsafeLoggers(empty_zone_map, 0);
544
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800545 int64_t timeout = 1;
546
547 std::string name1 = "temp1";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400548 std::unique_ptr<Sensor> sensor1 =
549 std::make_unique<SensorMock>(name1, timeout);
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800550 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
551
552 std::string name2 = "temp2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400553 std::unique_ptr<Sensor> sensor2 =
554 std::make_unique<SensorMock>(name2, timeout);
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800555 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
556
557 std::string type = "unchecked";
558 mgr.addSensor(type, name1, std::move(sensor1));
559 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
560 mgr.addSensor(type, name2, std::move(sensor2));
561 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
562
563 // Only sensor1 has MissingIsAcceptable enabled for it
564 zone->addThermalInput(name1, true);
565 zone->addThermalInput(name2, false);
566
567 // Initialize Zone
568 zone->initializeCache();
569
570 // As sensors are not initialized, zone should be in failsafe mode
571 EXPECT_TRUE(zone->getFailSafeMode());
572
573 // r1 not populated here, intentionally, to simulate a sensor that
574 // is not available yet, perhaps takes a long time to start up.
575 ReadReturn r1;
576 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
577
578 ReadReturn r2;
579 r2.value = 11.0;
580 r2.updated = std::chrono::high_resolution_clock::now();
581 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
582
583 zone->updateSensors();
584
585 // Only sensor2 has been initialized here. Failsafe should be false,
586 // because sensor1 MissingIsAcceptable so it is OK for it to go missing.
587 EXPECT_FALSE(zone->getFailSafeMode());
588
589 r1.value = 10.0;
590 r1.updated = std::chrono::high_resolution_clock::now();
591
592 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
593 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
594 zone->updateSensors();
595
596 // Both sensors are now properly initialized
597 EXPECT_FALSE(zone->getFailSafeMode());
598
599 // Ok, so we're not in failsafe mode, so let's set updated to the past.
600 // sensor1 will have an updated field older than its timeout value, but
601 // sensor2 will be fine. :D
602 r1.updated -= std::chrono::seconds(3);
603 r2.updated = std::chrono::high_resolution_clock::now();
604
605 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
606 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
607 zone->updateSensors();
608
609 // MissingIsAcceptable is true for sensor1, so the zone should not be
610 // thrown into failsafe mode.
611 EXPECT_FALSE(zone->getFailSafeMode());
612
613 // Do the same thing, but for the opposite sensors: r1 is good,
614 // but r2 is set to some time in the past.
615 r1.updated = std::chrono::high_resolution_clock::now();
616 r2.updated -= std::chrono::seconds(3);
617
618 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
619 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
620 zone->updateSensors();
621
622 // Now, the zone should be in failsafe mode, because sensor2 does not
623 // have MissingIsAcceptable set true, it is still subject to failsafe.
624 EXPECT_TRUE(zone->getFailSafeMode());
625
626 r1.updated = std::chrono::high_resolution_clock::now();
627 r2.updated = std::chrono::high_resolution_clock::now();
628
629 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
630 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
631 zone->updateSensors();
632
633 // The failsafe mode should cease, as both sensors are good again.
634 EXPECT_FALSE(zone->getFailSafeMode());
635}
636
Will Liangded0ab52019-05-15 17:10:06 +0800637TEST_F(PidZoneTest, FanInputTest_FailsafeToValid_ReadsSensors)
638{
639 // This will add a couple fan inputs, and verify the values are cached.
640
James Zheng6df8bb52024-11-27 23:38:47 +0000641 // Disable failsafe logger for the unit test.
642 std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> empty_zone_map;
643 buildFailsafeLoggers(empty_zone_map, 0);
644
Will Liangded0ab52019-05-15 17:10:06 +0800645 std::string name1 = "fan1";
646 int64_t timeout = 2;
647
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400648 std::unique_ptr<Sensor> sensor1 =
649 std::make_unique<SensorMock>(name1, timeout);
Will Liangded0ab52019-05-15 17:10:06 +0800650 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
651
652 std::string name2 = "fan2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400653 std::unique_ptr<Sensor> sensor2 =
654 std::make_unique<SensorMock>(name2, timeout);
Will Liangded0ab52019-05-15 17:10:06 +0800655 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
656
657 std::string type = "unchecked";
658 mgr.addSensor(type, name1, std::move(sensor1));
659 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
660 mgr.addSensor(type, name2, std::move(sensor2));
661 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
662
663 // Now that the sensors exist, add them to the zone.
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800664 zone->addFanInput(name1, false);
665 zone->addFanInput(name2, false);
Will Liangded0ab52019-05-15 17:10:06 +0800666
667 // Initialize Zone
668 zone->initializeCache();
669
670 // Verify now in failsafe mode.
671 EXPECT_TRUE(zone->getFailSafeMode());
672
673 ReadReturn r1;
674 r1.value = 10.0;
675 r1.updated = std::chrono::high_resolution_clock::now();
676 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
677
678 ReadReturn r2;
679 r2.value = 11.0;
680 r2.updated = std::chrono::high_resolution_clock::now();
681 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
682
683 // Method under test will read through each fan sensor for the zone and
684 // cache the values.
685 zone->updateFanTelemetry();
686
687 // We should no longer be in failsafe mode.
688 EXPECT_FALSE(zone->getFailSafeMode());
689
690 EXPECT_EQ(r1.value, zone->getCachedValue(name1));
691 EXPECT_EQ(r2.value, zone->getCachedValue(name2));
692}
693
694TEST_F(PidZoneTest, FanInputTest_ValueTimeoutEntersFailSafeMode)
695{
696 // This will add a couple fan inputs, and verify the values are cached.
697
James Zheng6df8bb52024-11-27 23:38:47 +0000698 // Disable failsafe logger for the unit test.
699 std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> empty_zone_map;
700 buildFailsafeLoggers(empty_zone_map, 0);
701
Will Liangded0ab52019-05-15 17:10:06 +0800702 std::string name1 = "fan1";
703 int64_t timeout = 2;
704
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400705 std::unique_ptr<Sensor> sensor1 =
706 std::make_unique<SensorMock>(name1, timeout);
Will Liangded0ab52019-05-15 17:10:06 +0800707 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
708
709 std::string name2 = "fan2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400710 std::unique_ptr<Sensor> sensor2 =
711 std::make_unique<SensorMock>(name2, timeout);
Will Liangded0ab52019-05-15 17:10:06 +0800712 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
713
714 std::string type = "unchecked";
715 mgr.addSensor(type, name1, std::move(sensor1));
716 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
717 mgr.addSensor(type, name2, std::move(sensor2));
718 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
719
720 // Now that the sensors exist, add them to the zone.
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800721 zone->addFanInput(name1, false);
722 zone->addFanInput(name2, false);
Will Liangded0ab52019-05-15 17:10:06 +0800723
724 // Initialize Zone
725 zone->initializeCache();
726
727 // Verify now in failsafe mode.
728 EXPECT_TRUE(zone->getFailSafeMode());
729
730 ReadReturn r1;
731 r1.value = 10.0;
732 r1.updated = std::chrono::high_resolution_clock::now();
733 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
734
735 ReadReturn r2;
736 r2.value = 11.0;
737 r2.updated = std::chrono::high_resolution_clock::now();
738 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
739
740 // Method under test will read through each fan sensor for the zone and
741 // cache the values.
742 zone->updateFanTelemetry();
743
744 // We should no longer be in failsafe mode.
745 EXPECT_FALSE(zone->getFailSafeMode());
746
747 r1.updated -= std::chrono::seconds(3);
748 r2.updated = std::chrono::high_resolution_clock::now();
749
750 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
751 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
752
753 zone->updateFanTelemetry();
754 EXPECT_TRUE(zone->getFailSafeMode());
755}
756
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700757TEST_F(PidZoneTest, GetSensorTest_ReturnsExpected)
758{
Patrick Venturea58197c2018-06-11 15:29:45 -0700759 // One can grab a sensor from the manager through the zone.
760
James Zheng6df8bb52024-11-27 23:38:47 +0000761 // Disable failsafe logger for the unit test.
762 std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> empty_zone_map;
763 buildFailsafeLoggers(empty_zone_map, 0);
764
Patrick Venturea58197c2018-06-11 15:29:45 -0700765 int64_t timeout = 1;
766
767 std::string name1 = "temp1";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400768 std::unique_ptr<Sensor> sensor1 =
769 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700770 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700771
772 std::string type = "unchecked";
773 mgr.addSensor(type, name1, std::move(sensor1));
774 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
775
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800776 zone->addThermalInput(name1, false);
Patrick Venturea58197c2018-06-11 15:29:45 -0700777
778 // Verify method under test returns the pointer we expect.
779 EXPECT_EQ(mgr.getSensor(name1), zone->getSensor(name1));
780}
781
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700782TEST_F(PidZoneTest, AddThermalPIDTest_VerifiesThermalPIDsProcessed)
783{
Patrick Venturea58197c2018-06-11 15:29:45 -0700784 // Tests adding a thermal PID controller to the zone, and verifies it's
785 // touched during processing.
786
787 std::unique_ptr<PIDController> tpid =
788 std::make_unique<ControllerMock>("thermal1", zone.get());
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700789 ControllerMock* tmock = reinterpret_cast<ControllerMock*>(tpid.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700790
791 // Access the internal pid configuration to clear it out (unrelated to the
792 // test).
Harvey Wu1b3b7302024-10-04 16:49:46 +0800793 [[maybe_unused]] ec::pid_info_t* info = tpid->getPIDInfo();
Patrick Venturea58197c2018-06-11 15:29:45 -0700794
795 zone->addThermalPID(std::move(tpid));
796
Patrick Venture563a3562018-10-30 09:31:26 -0700797 EXPECT_CALL(*tmock, setptProc()).WillOnce(Return(10.0));
798 EXPECT_CALL(*tmock, inputProc()).WillOnce(Return(11.0));
799 EXPECT_CALL(*tmock, outputProc(_));
Patrick Venturea58197c2018-06-11 15:29:45 -0700800
801 // Method under test will, for each thermal PID, call setpt, input, and
802 // output.
Patrick Venture563a3562018-10-30 09:31:26 -0700803 zone->processThermals();
Patrick Venturea58197c2018-06-11 15:29:45 -0700804}
805
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700806TEST_F(PidZoneTest, AddFanPIDTest_VerifiesFanPIDsProcessed)
807{
Patrick Venturea58197c2018-06-11 15:29:45 -0700808 // Tests adding a fan PID controller to the zone, and verifies it's
809 // touched during processing.
810
811 std::unique_ptr<PIDController> tpid =
812 std::make_unique<ControllerMock>("fan1", zone.get());
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700813 ControllerMock* tmock = reinterpret_cast<ControllerMock*>(tpid.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700814
815 // Access the internal pid configuration to clear it out (unrelated to the
816 // test).
Harvey Wu1b3b7302024-10-04 16:49:46 +0800817 [[maybe_unused]] ec::pid_info_t* info = tpid->getPIDInfo();
Patrick Venturea58197c2018-06-11 15:29:45 -0700818
819 zone->addFanPID(std::move(tpid));
820
Patrick Venture563a3562018-10-30 09:31:26 -0700821 EXPECT_CALL(*tmock, setptProc()).WillOnce(Return(10.0));
822 EXPECT_CALL(*tmock, inputProc()).WillOnce(Return(11.0));
823 EXPECT_CALL(*tmock, outputProc(_));
Patrick Venturea58197c2018-06-11 15:29:45 -0700824
825 // Method under test will, for each fan PID, call setpt, input, and output.
Patrick Venture563a3562018-10-30 09:31:26 -0700826 zone->processFans();
Patrick Venturea58197c2018-06-11 15:29:45 -0700827}
828
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700829TEST_F(PidZoneTest, ManualModeDbusTest_VerifySetManualBehavesAsExpected)
830{
Patrick Venturea58197c2018-06-11 15:29:45 -0700831 // The manual(bool) method is inherited from the dbus mode interface.
832
833 // Verifies that someone doesn't remove the internal call to the dbus
834 // object from which we're inheriting.
835 EXPECT_CALL(sdbus_mock_mode,
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700836 sd_bus_emit_properties_changed_strv(
837 IsNull(), StrEq(objPath), StrEq(modeInterface), NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800838 .WillOnce(Invoke(
839 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
840 [[maybe_unused]] const char* interface, const char** names) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400841 EXPECT_STREQ("Manual", names[0]);
842 return 0;
843 }));
Patrick Venturea58197c2018-06-11 15:29:45 -0700844
845 // Method under test will set the manual mode to true and broadcast this
846 // change on dbus.
847 zone->manual(true);
848 EXPECT_TRUE(zone->getManualMode());
849}
850
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700851TEST_F(PidZoneTest, FailsafeDbusTest_VerifiesReturnsExpected)
852{
Patrick Venturea58197c2018-06-11 15:29:45 -0700853 // This property is implemented by us as read-only, such that trying to
854 // write to it will have no effect.
James Zheng6df8bb52024-11-27 23:38:47 +0000855
856 // Disable failsafe logger for the unit test.
857 std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> empty_zone_map;
858 buildFailsafeLoggers(empty_zone_map, 0);
859
Patrick Venturea58197c2018-06-11 15:29:45 -0700860 EXPECT_EQ(zone->failSafe(), zone->getFailSafeMode());
861}
Patrick Venturea0764872020-08-08 07:48:43 -0700862
863} // namespace
864} // namespace pid_control