blob: 51559710ff71f84c9111cc1b73cf20216c308baa [file] [log] [blame]
Josh Lehande745422020-11-07 02:14:09 -08001#include "pid/ec/logging.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07002#include "pid/ec/pid.hpp"
Patrick Venturea58197c2018-06-11 15:29:45 -07003#include "pid/zone.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07004#include "sensors/manager.hpp"
5#include "test/controller_mock.hpp"
6#include "test/helpers.hpp"
7#include "test/sensor_mock.hpp"
Patrick Venturea58197c2018-06-11 15:29:45 -07008
Patrick Venturea83a3ec2020-08-04 09:52:05 -07009#include <sdbusplus/test/sdbus_mock.hpp>
10
Patrick Venturea58197c2018-06-11 15:29:45 -070011#include <chrono>
12#include <cstring>
Patrick Venturea58197c2018-06-11 15:29:45 -070013#include <vector>
14
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070015#include <gmock/gmock.h>
16#include <gtest/gtest.h>
Patrick Venturea58197c2018-06-11 15:29:45 -070017
Patrick Venturea0764872020-08-08 07:48:43 -070018namespace pid_control
19{
20namespace
21{
22
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070023using ::testing::_;
Patrick Venturea58197c2018-06-11 15:29:45 -070024using ::testing::IsNull;
25using ::testing::Return;
26using ::testing::StrEq;
Patrick Venturea58197c2018-06-11 15:29:45 -070027
28static std::string modeInterface = "xyz.openbmc_project.Control.Mode";
Harvey Wucc0232a2023-02-09 14:58:55 +080029static std::string debugZoneInterface = "xyz.openbmc_project.Debug.Pid.Zone";
ykchiu7c6d35d2023-05-10 17:01:46 +080030static std::string enableInterface = "xyz.openbmc_project.Object.Enable";
Harvey Wu37180062023-10-02 09:42:50 +080031static std::string debugThermalPowerInterface =
32 "xyz.openbmc_project.Debug.Pid.ThermalPower";
Patrick Venturea58197c2018-06-11 15:29:45 -070033
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070034namespace
35{
Patrick Venturea58197c2018-06-11 15:29:45 -070036
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070037TEST(PidZoneConstructorTest, BoringConstructorTest)
38{
Patrick Venturea58197c2018-06-11 15:29:45 -070039 // Build a PID Zone.
40
ykchiu7c6d35d2023-05-10 17:01:46 +080041 sdbusplus::SdBusMock sdbus_mock_passive, sdbus_mock_host, sdbus_mock_mode,
42 sdbus_mock_enable;
Patrick Venturea58197c2018-06-11 15:29:45 -070043 auto bus_mock_passive = sdbusplus::get_mocked_new(&sdbus_mock_passive);
44 auto bus_mock_host = sdbusplus::get_mocked_new(&sdbus_mock_host);
45 auto bus_mock_mode = sdbusplus::get_mocked_new(&sdbus_mock_mode);
ykchiu7c6d35d2023-05-10 17:01:46 +080046 auto bus_mock_enable = sdbusplus::get_mocked_new(&sdbus_mock_enable);
Patrick Venturea58197c2018-06-11 15:29:45 -070047
48 EXPECT_CALL(sdbus_mock_host,
49 sd_bus_add_object_manager(
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070050 IsNull(), _, StrEq("/xyz/openbmc_project/extsensors")))
Patrick Venturea58197c2018-06-11 15:29:45 -070051 .WillOnce(Return(0));
52
James Feist1fe08952019-05-07 09:17:16 -070053 SensorManager m(bus_mock_passive, bus_mock_host);
Patrick Venturea58197c2018-06-11 15:29:45 -070054
55 bool defer = true;
Delphine CC Chiu97889632023-11-06 11:32:46 +080056 bool accSetPoint = false;
Patrick Venturee2ec0f62018-09-04 12:30:27 -070057 const char* objPath = "/path/";
Patrick Venturea58197c2018-06-11 15:29:45 -070058 int64_t zone = 1;
James Feist3484bed2019-02-25 13:28:18 -080059 double minThermalOutput = 1000.0;
Harvey Wu92f9f3c2023-11-07 09:23:35 +080060 double failSafePercent = 100;
Bonnie Lo0e8fc392022-10-05 10:20:55 +080061 conf::CycleTime cycleTime;
Patrick Venturea58197c2018-06-11 15:29:45 -070062
James Feist0709e2f2020-07-08 10:59:45 -070063 double d;
Patrick Venturea58197c2018-06-11 15:29:45 -070064 std::vector<std::string> properties;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070065 SetupDbusObject(&sdbus_mock_mode, defer, objPath, modeInterface, properties,
James Feist0709e2f2020-07-08 10:59:45 -070066 &d);
Harvey Wucc0232a2023-02-09 14:58:55 +080067 SetupDbusObject(&sdbus_mock_mode, defer, objPath, debugZoneInterface,
68 properties, &d);
Patrick Venturea58197c2018-06-11 15:29:45 -070069
ykchiu7c6d35d2023-05-10 17:01:46 +080070 std::string sensorname = "temp1";
Patrick Williamsbd63bca2024-08-16 15:21:10 -040071 std::string pidsensorpath =
72 "/xyz/openbmc_project/settings/fanctrl/zone1/" + sensorname;
ykchiu7c6d35d2023-05-10 17:01:46 +080073
74 double de;
75 std::vector<std::string> propertiesenable;
76 SetupDbusObject(&sdbus_mock_enable, defer, pidsensorpath.c_str(),
77 enableInterface, propertiesenable, &de);
78
Bonnie Lo0e8fc392022-10-05 10:20:55 +080079 DbusPidZone p(zone, minThermalOutput, failSafePercent, cycleTime, m,
Delphine CC Chiu97889632023-11-06 11:32:46 +080080 bus_mock_mode, objPath, defer, accSetPoint);
Patrick Venturea58197c2018-06-11 15:29:45 -070081 // Success.
82}
83
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070084} // namespace
Patrick Venturea58197c2018-06-11 15:29:45 -070085
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070086class PidZoneTest : public ::testing::Test
87{
88 protected:
89 PidZoneTest() :
90 property_index(), properties(), sdbus_mock_passive(), sdbus_mock_host(),
ykchiu7c6d35d2023-05-10 17:01:46 +080091 sdbus_mock_mode(), sdbus_mock_enable()
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070092 {
93 EXPECT_CALL(sdbus_mock_host,
94 sd_bus_add_object_manager(
95 IsNull(), _, StrEq("/xyz/openbmc_project/extsensors")))
96 .WillOnce(Return(0));
Patrick Venturea58197c2018-06-11 15:29:45 -070097
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070098 auto bus_mock_passive = sdbusplus::get_mocked_new(&sdbus_mock_passive);
99 auto bus_mock_host = sdbusplus::get_mocked_new(&sdbus_mock_host);
100 auto bus_mock_mode = sdbusplus::get_mocked_new(&sdbus_mock_mode);
ykchiu7c6d35d2023-05-10 17:01:46 +0800101 auto bus_mock_enable = sdbusplus::get_mocked_new(&sdbus_mock_enable);
Patrick Venturea58197c2018-06-11 15:29:45 -0700102
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700103 // Compiler weirdly not happy about just instantiating mgr(...);
James Feist1fe08952019-05-07 09:17:16 -0700104 SensorManager m(bus_mock_passive, bus_mock_host);
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700105 mgr = std::move(m);
Patrick Venturea58197c2018-06-11 15:29:45 -0700106
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700107 SetupDbusObject(&sdbus_mock_mode, defer, objPath, modeInterface,
108 properties, &property_index);
Harvey Wucc0232a2023-02-09 14:58:55 +0800109 SetupDbusObject(&sdbus_mock_mode, defer, objPath, debugZoneInterface,
110 properties, &property_index);
Patrick Venturea58197c2018-06-11 15:29:45 -0700111
ykchiu7c6d35d2023-05-10 17:01:46 +0800112 SetupDbusObject(&sdbus_mock_enable, defer, pidsensorpath.c_str(),
113 enableInterface, propertiesenable,
114 &propertyenable_index);
115
Delphine CC Chiu97889632023-11-06 11:32:46 +0800116 zone = std::make_unique<DbusPidZone>(
117 zoneId, minThermalOutput, failSafePercent, cycleTime, mgr,
118 bus_mock_mode, objPath, defer, accSetPoint);
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700119 }
Patrick Venturea58197c2018-06-11 15:29:45 -0700120
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700121 // unused
James Feist0709e2f2020-07-08 10:59:45 -0700122 double property_index;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700123 std::vector<std::string> properties;
ykchiu7c6d35d2023-05-10 17:01:46 +0800124 double propertyenable_index;
125 std::vector<std::string> propertiesenable;
Patrick Venturea58197c2018-06-11 15:29:45 -0700126
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700127 sdbusplus::SdBusMock sdbus_mock_passive;
128 sdbusplus::SdBusMock sdbus_mock_host;
129 sdbusplus::SdBusMock sdbus_mock_mode;
ykchiu7c6d35d2023-05-10 17:01:46 +0800130 sdbusplus::SdBusMock sdbus_mock_enable;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700131 int64_t zoneId = 1;
James Feist3484bed2019-02-25 13:28:18 -0800132 double minThermalOutput = 1000.0;
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800133 double failSafePercent = 100;
Harvey Wu37180062023-10-02 09:42:50 +0800134 double setpoint = 50.0;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700135 bool defer = true;
Delphine CC Chiu97889632023-11-06 11:32:46 +0800136 bool accSetPoint = false;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700137 const char* objPath = "/path/";
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700138 SensorManager mgr;
Bonnie Lo0e8fc392022-10-05 10:20:55 +0800139 conf::CycleTime cycleTime;
Patrick Venturea58197c2018-06-11 15:29:45 -0700140
ykchiu7c6d35d2023-05-10 17:01:46 +0800141 std::string sensorname = "temp1";
Harvey Wu37180062023-10-02 09:42:50 +0800142 std::string sensorType = "temp";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400143 std::string pidsensorpath =
144 "/xyz/openbmc_project/settings/fanctrl/zone1/" + sensorname;
ykchiu7c6d35d2023-05-10 17:01:46 +0800145
Patrick Venture597ebd62020-08-11 08:48:19 -0700146 std::unique_ptr<DbusPidZone> zone;
Patrick Venturea58197c2018-06-11 15:29:45 -0700147};
148
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700149TEST_F(PidZoneTest, GetZoneId_ReturnsExpected)
150{
Patrick Venturea58197c2018-06-11 15:29:45 -0700151 // Verifies the zoneId returned is what we expect.
152
Patrick Venture0bbeaf82018-10-30 18:50:31 -0700153 EXPECT_EQ(zoneId, zone->getZoneID());
Patrick Venturea58197c2018-06-11 15:29:45 -0700154}
155
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700156TEST_F(PidZoneTest, GetAndSetManualModeTest_BehavesAsExpected)
157{
Patrick Venturea58197c2018-06-11 15:29:45 -0700158 // Verifies that the zone starts in manual mode. Verifies that one can set
159 // the mode.
160 EXPECT_FALSE(zone->getManualMode());
161
162 zone->setManualMode(true);
163 EXPECT_TRUE(zone->getManualMode());
164}
165
ykchiu7c6d35d2023-05-10 17:01:46 +0800166TEST_F(PidZoneTest, AddPidControlProcessGetAndSetEnableTest_BehavesAsExpected)
167{
168 // Verifies that the zone starts in enable mode. Verifies that one can set
169 // enable the mode.
170 auto bus_mock_enable = sdbusplus::get_mocked_new(&sdbus_mock_enable);
171
172 EXPECT_CALL(sdbus_mock_mode, sd_bus_emit_properties_changed_strv(
173 IsNull(), StrEq(pidsensorpath.c_str()),
174 StrEq(enableInterface), NotNull()))
175 .Times(::testing::AnyNumber())
176 .WillOnce(Invoke(
177 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
178 [[maybe_unused]] const char* interface, const char** names) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400179 EXPECT_STREQ("Enable", names[0]);
180 return 0;
181 }));
ykchiu7c6d35d2023-05-10 17:01:46 +0800182
Harvey Wu37180062023-10-02 09:42:50 +0800183 zone->addPidControlProcess(sensorname, sensorType, setpoint,
184 bus_mock_enable, pidsensorpath.c_str(), defer);
ykchiu7c6d35d2023-05-10 17:01:46 +0800185 EXPECT_TRUE(zone->isPidProcessEnabled(sensorname));
186}
187
Josh Lehana4146eb2020-10-01 11:49:09 -0700188TEST_F(PidZoneTest, SetManualMode_RedundantWritesEnabledOnceAfterManualMode)
189{
190 // Tests adding a fan PID controller to the zone, and verifies it's
191 // touched during processing.
192
193 std::unique_ptr<PIDController> tpid =
194 std::make_unique<ControllerMock>("fan1", zone.get());
195 ControllerMock* tmock = reinterpret_cast<ControllerMock*>(tpid.get());
196
197 // Access the internal pid configuration to clear it out (unrelated to the
198 // test).
Harvey Wu1b3b7302024-10-04 16:49:46 +0800199 [[maybe_unused]] ec::pid_info_t* info = tpid->getPIDInfo();
Josh Lehana4146eb2020-10-01 11:49:09 -0700200
201 zone->addFanPID(std::move(tpid));
202
203 EXPECT_CALL(*tmock, setptProc()).WillOnce(Return(10.0));
204 EXPECT_CALL(*tmock, inputProc()).WillOnce(Return(11.0));
205 EXPECT_CALL(*tmock, outputProc(_));
206
207 // while zone is in auto mode redundant writes should be disabled
208 EXPECT_FALSE(zone->getRedundantWrite());
209
210 // but switching from manual to auto enables a single redundant write
211 zone->setManualMode(true);
212 zone->setManualMode(false);
213 EXPECT_TRUE(zone->getRedundantWrite());
214
215 // after one iteration of a pid loop redundant write should be cleared
216 zone->processFans();
217 EXPECT_FALSE(zone->getRedundantWrite());
218}
219
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700220TEST_F(PidZoneTest, RpmSetPoints_AddMaxClear_BehaveAsExpected)
221{
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700222 // Tests addSetPoint, clearSetPoints, determineMaxSetPointRequest
Nirav Shahccc8bb62022-02-17 21:06:51 -0800223 // and getMinThermalSetPoint.
Patrick Venturea58197c2018-06-11 15:29:45 -0700224
ykchiu7c6d35d2023-05-10 17:01:46 +0800225 // Need to add pid control process for the zone that can enable
226 // the process and add the set point.
227 auto bus_mock_enable = sdbusplus::get_mocked_new(&sdbus_mock_enable);
228
229 EXPECT_CALL(sdbus_mock_mode, sd_bus_emit_properties_changed_strv(
230 IsNull(), StrEq(pidsensorpath.c_str()),
231 StrEq(enableInterface), NotNull()))
232 .Times(::testing::AnyNumber())
233 .WillOnce(Invoke(
234 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
235 [[maybe_unused]] const char* interface, const char** names) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400236 EXPECT_STREQ("Enable", names[0]);
237 return 0;
238 }));
ykchiu7c6d35d2023-05-10 17:01:46 +0800239
Harvey Wu37180062023-10-02 09:42:50 +0800240 zone->addPidControlProcess(sensorname, sensorType, setpoint,
241 bus_mock_enable, pidsensorpath.c_str(), defer);
ykchiu7c6d35d2023-05-10 17:01:46 +0800242
Patrick Venturea58197c2018-06-11 15:29:45 -0700243 // At least one value must be above the minimum thermal setpoint used in
244 // the constructor otherwise it'll choose that value
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800245 std::vector<double> values = {100, 200, 300, 400, 500, 5000};
ykchiu7c6d35d2023-05-10 17:01:46 +0800246
Patrick Venturea58197c2018-06-11 15:29:45 -0700247 for (auto v : values)
248 {
ykchiu7c6d35d2023-05-10 17:01:46 +0800249 zone->addSetPoint(v, sensorname);
Patrick Venturea58197c2018-06-11 15:29:45 -0700250 }
251
252 // This will pull the maximum RPM setpoint request.
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700253 zone->determineMaxSetPointRequest();
254 EXPECT_EQ(5000, zone->getMaxSetPointRequest());
Patrick Venturea58197c2018-06-11 15:29:45 -0700255
256 // Clear the values, so it'll choose the minimum thermal setpoint.
Patrick Venture9bbf3332019-07-16 10:50:37 -0700257 zone->clearSetPoints();
Patrick Venturea58197c2018-06-11 15:29:45 -0700258
259 // This will go through the RPM set point values and grab the maximum.
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700260 zone->determineMaxSetPointRequest();
Nirav Shahccc8bb62022-02-17 21:06:51 -0800261 EXPECT_EQ(zone->getMinThermalSetPoint(), zone->getMaxSetPointRequest());
Patrick Venturea58197c2018-06-11 15:29:45 -0700262}
263
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700264TEST_F(PidZoneTest, RpmSetPoints_AddBelowMinimum_BehavesAsExpected)
265{
Patrick Venturea58197c2018-06-11 15:29:45 -0700266 // Tests adding several RPM setpoints, however, they're all lower than the
Patrick Venture7280e272019-02-11 10:45:32 -0800267 // configured minimal thermal setpoint RPM value.
Patrick Venturea58197c2018-06-11 15:29:45 -0700268
ykchiu7c6d35d2023-05-10 17:01:46 +0800269 // Need to add pid control process for the zone that can enable
270 // the process and add the set point.
271 auto bus_mock_enable = sdbusplus::get_mocked_new(&sdbus_mock_enable);
272
273 EXPECT_CALL(sdbus_mock_mode, sd_bus_emit_properties_changed_strv(
274 IsNull(), StrEq(pidsensorpath.c_str()),
275 StrEq(enableInterface), NotNull()))
276 .Times(::testing::AnyNumber())
277 .WillOnce(Invoke(
278 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
279 [[maybe_unused]] const char* interface, const char** names) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400280 EXPECT_STREQ("Enable", names[0]);
281 return 0;
282 }));
ykchiu7c6d35d2023-05-10 17:01:46 +0800283
Harvey Wu37180062023-10-02 09:42:50 +0800284 zone->addPidControlProcess(sensorname, sensorType, setpoint,
285 bus_mock_enable, pidsensorpath.c_str(), defer);
ykchiu7c6d35d2023-05-10 17:01:46 +0800286
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800287 std::vector<double> values = {100, 200, 300, 400, 500};
ykchiu7c6d35d2023-05-10 17:01:46 +0800288
Patrick Venturea58197c2018-06-11 15:29:45 -0700289 for (auto v : values)
290 {
ykchiu7c6d35d2023-05-10 17:01:46 +0800291 zone->addSetPoint(v, sensorname);
Patrick Venturea58197c2018-06-11 15:29:45 -0700292 }
293
294 // This will pull the maximum RPM setpoint request.
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700295 zone->determineMaxSetPointRequest();
Patrick Venturea58197c2018-06-11 15:29:45 -0700296
297 // Verifies the value returned in the minimal thermal rpm set point.
Nirav Shahccc8bb62022-02-17 21:06:51 -0800298 EXPECT_EQ(zone->getMinThermalSetPoint(), zone->getMaxSetPointRequest());
Patrick Venturea58197c2018-06-11 15:29:45 -0700299}
300
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800301TEST_F(PidZoneTest, GetFailSafePercent_SingleFailedReturnsExpected)
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700302{
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800303 // Tests when only one sensor failed and the sensor's failsafe duty is zero,
304 // and verify that the sensor name is empty and failsafe duty is PID zone's
305 // failsafe duty.
ykchiu9fe3a3c2023-05-11 13:43:54 +0800306
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800307 std::vector<std::string> input1 = {"temp1"};
308 std::vector<std::string> input2 = {"temp2"};
309 std::vector<std::string> input3 = {"temp3"};
ykchiu9fe3a3c2023-05-11 13:43:54 +0800310 std::vector<double> values = {0, 0, 0};
ykchiu9fe3a3c2023-05-11 13:43:54 +0800311
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800312 zone->addPidFailSafePercent(input1, values[0]);
313 zone->addPidFailSafePercent(input2, values[1]);
314 zone->addPidFailSafePercent(input3, values[2]);
ykchiu9fe3a3c2023-05-11 13:43:54 +0800315
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800316 zone->markSensorMissing("temp1");
ykchiu9fe3a3c2023-05-11 13:43:54 +0800317
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800318 EXPECT_EQ(failSafePercent, zone->getFailSafePercent());
ykchiu9fe3a3c2023-05-11 13:43:54 +0800319}
320
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800321TEST_F(PidZoneTest, GetFailSafePercent_MultiFailedReturnsExpected)
ykchiu9fe3a3c2023-05-11 13:43:54 +0800322{
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800323 // Tests when multi sensor failed, and verify the final failsafe's sensor
324 // name and duty as expected.
ykchiu9fe3a3c2023-05-11 13:43:54 +0800325
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800326 std::vector<std::string> input1 = {"temp1"};
327 std::vector<std::string> input2 = {"temp2"};
328 std::vector<std::string> input3 = {"temp3"};
ykchiu9fe3a3c2023-05-11 13:43:54 +0800329 std::vector<double> values = {60, 80, 70};
ykchiu9fe3a3c2023-05-11 13:43:54 +0800330
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800331 zone->addPidFailSafePercent(input1, values[0]);
332 zone->addPidFailSafePercent(input2, values[1]);
333 zone->addPidFailSafePercent(input3, values[2]);
ykchiu9fe3a3c2023-05-11 13:43:54 +0800334
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800335 zone->markSensorMissing("temp1");
336 zone->markSensorMissing("temp2");
337 zone->markSensorMissing("temp3");
ykchiu9fe3a3c2023-05-11 13:43:54 +0800338
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800339 EXPECT_EQ(80, zone->getFailSafePercent());
Patrick Venturea58197c2018-06-11 15:29:45 -0700340}
341
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700342TEST_F(PidZoneTest, ThermalInputs_FailsafeToValid_ReadsSensors)
343{
Patrick Venturea58197c2018-06-11 15:29:45 -0700344 // This test will add a couple thermal inputs, and verify that the zone
345 // initializes into failsafe mode, and will read each sensor.
346
347 std::string name1 = "temp1";
348 int64_t timeout = 1;
349
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400350 std::unique_ptr<Sensor> sensor1 =
351 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700352 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700353
354 std::string name2 = "temp2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400355 std::unique_ptr<Sensor> sensor2 =
356 std::make_unique<SensorMock>(name2, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700357 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700358
359 std::string type = "unchecked";
360 mgr.addSensor(type, name1, std::move(sensor1));
361 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
362 mgr.addSensor(type, name2, std::move(sensor2));
363 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
364
365 // Now that the sensors exist, add them to the zone.
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800366 zone->addThermalInput(name1, false);
367 zone->addThermalInput(name2, false);
Patrick Venturea58197c2018-06-11 15:29:45 -0700368
369 // Initialize Zone
370 zone->initializeCache();
371
372 // Verify now in failsafe mode.
373 EXPECT_TRUE(zone->getFailSafeMode());
374
375 ReadReturn r1;
376 r1.value = 10.0;
377 r1.updated = std::chrono::high_resolution_clock::now();
378 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
379
380 ReadReturn r2;
381 r2.value = 11.0;
382 r2.updated = std::chrono::high_resolution_clock::now();
383 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
384
385 // Read the sensors, this will put the values into the cache.
386 zone->updateSensors();
387
388 // We should no longer be in failsafe mode.
389 EXPECT_FALSE(zone->getFailSafeMode());
390
391 EXPECT_EQ(r1.value, zone->getCachedValue(name1));
392 EXPECT_EQ(r2.value, zone->getCachedValue(name2));
393}
394
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700395TEST_F(PidZoneTest, FanInputTest_VerifiesFanValuesCached)
396{
Patrick Venturea58197c2018-06-11 15:29:45 -0700397 // This will add a couple fan inputs, and verify the values are cached.
398
399 std::string name1 = "fan1";
400 int64_t timeout = 2;
401
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400402 std::unique_ptr<Sensor> sensor1 =
403 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700404 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700405
406 std::string name2 = "fan2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400407 std::unique_ptr<Sensor> sensor2 =
408 std::make_unique<SensorMock>(name2, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700409 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700410
411 std::string type = "unchecked";
412 mgr.addSensor(type, name1, std::move(sensor1));
413 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
414 mgr.addSensor(type, name2, std::move(sensor2));
415 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
416
417 // Now that the sensors exist, add them to the zone.
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800418 zone->addFanInput(name1, false);
419 zone->addFanInput(name2, false);
Patrick Venturea58197c2018-06-11 15:29:45 -0700420
421 // Initialize Zone
422 zone->initializeCache();
423
424 ReadReturn r1;
425 r1.value = 10.0;
426 r1.updated = std::chrono::high_resolution_clock::now();
427 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
428
429 ReadReturn r2;
430 r2.value = 11.0;
431 r2.updated = std::chrono::high_resolution_clock::now();
432 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
433
434 // Method under test will read through each fan sensor for the zone and
435 // cache the values.
436 zone->updateFanTelemetry();
437
438 EXPECT_EQ(r1.value, zone->getCachedValue(name1));
439 EXPECT_EQ(r2.value, zone->getCachedValue(name2));
440}
441
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700442TEST_F(PidZoneTest, ThermalInput_ValueTimeoutEntersFailSafeMode)
443{
Patrick Venturea58197c2018-06-11 15:29:45 -0700444 // On the second updateSensors call, the updated timestamp will be beyond
445 // the timeout limit.
446
447 int64_t timeout = 1;
448
449 std::string name1 = "temp1";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400450 std::unique_ptr<Sensor> sensor1 =
451 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700452 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700453
454 std::string name2 = "temp2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400455 std::unique_ptr<Sensor> sensor2 =
456 std::make_unique<SensorMock>(name2, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700457 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700458
459 std::string type = "unchecked";
460 mgr.addSensor(type, name1, std::move(sensor1));
461 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
462 mgr.addSensor(type, name2, std::move(sensor2));
463 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
464
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800465 zone->addThermalInput(name1, false);
466 zone->addThermalInput(name2, false);
Patrick Venturea58197c2018-06-11 15:29:45 -0700467
468 // Initialize Zone
469 zone->initializeCache();
470
471 // Verify now in failsafe mode.
472 EXPECT_TRUE(zone->getFailSafeMode());
473
474 ReadReturn r1;
475 r1.value = 10.0;
476 r1.updated = std::chrono::high_resolution_clock::now();
477 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
478
479 ReadReturn r2;
480 r2.value = 11.0;
481 r2.updated = std::chrono::high_resolution_clock::now();
482 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
483
484 zone->updateSensors();
485 EXPECT_FALSE(zone->getFailSafeMode());
486
487 // Ok, so we're not in failsafe mode, so let's set updated to the past.
488 // sensor1 will have an updated field older than its timeout value, but
489 // sensor2 will be fine. :D
490 r1.updated -= std::chrono::seconds(3);
491 r2.updated = std::chrono::high_resolution_clock::now();
492
493 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
494 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
495
496 // Method under test will read each sensor. One sensor's value is older
497 // than the timeout for that sensor and this triggers failsafe mode.
498 zone->updateSensors();
499 EXPECT_TRUE(zone->getFailSafeMode());
500}
501
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800502TEST_F(PidZoneTest, ThermalInput_MissingIsAcceptableNoFailSafe)
503{
504 // This is similar to the above test, but because missingIsAcceptable
505 // is set for sensor1, the zone should not enter failsafe mode when
506 // only sensor1 goes missing.
507 // However, sensor2 going missing should still trigger failsafe mode.
508
509 int64_t timeout = 1;
510
511 std::string name1 = "temp1";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400512 std::unique_ptr<Sensor> sensor1 =
513 std::make_unique<SensorMock>(name1, timeout);
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800514 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
515
516 std::string name2 = "temp2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400517 std::unique_ptr<Sensor> sensor2 =
518 std::make_unique<SensorMock>(name2, timeout);
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800519 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
520
521 std::string type = "unchecked";
522 mgr.addSensor(type, name1, std::move(sensor1));
523 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
524 mgr.addSensor(type, name2, std::move(sensor2));
525 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
526
527 // Only sensor1 has MissingIsAcceptable enabled for it
528 zone->addThermalInput(name1, true);
529 zone->addThermalInput(name2, false);
530
531 // Initialize Zone
532 zone->initializeCache();
533
534 // As sensors are not initialized, zone should be in failsafe mode
535 EXPECT_TRUE(zone->getFailSafeMode());
536
537 // r1 not populated here, intentionally, to simulate a sensor that
538 // is not available yet, perhaps takes a long time to start up.
539 ReadReturn r1;
540 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
541
542 ReadReturn r2;
543 r2.value = 11.0;
544 r2.updated = std::chrono::high_resolution_clock::now();
545 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
546
547 zone->updateSensors();
548
549 // Only sensor2 has been initialized here. Failsafe should be false,
550 // because sensor1 MissingIsAcceptable so it is OK for it to go missing.
551 EXPECT_FALSE(zone->getFailSafeMode());
552
553 r1.value = 10.0;
554 r1.updated = std::chrono::high_resolution_clock::now();
555
556 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
557 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
558 zone->updateSensors();
559
560 // Both sensors are now properly initialized
561 EXPECT_FALSE(zone->getFailSafeMode());
562
563 // Ok, so we're not in failsafe mode, so let's set updated to the past.
564 // sensor1 will have an updated field older than its timeout value, but
565 // sensor2 will be fine. :D
566 r1.updated -= std::chrono::seconds(3);
567 r2.updated = std::chrono::high_resolution_clock::now();
568
569 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
570 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
571 zone->updateSensors();
572
573 // MissingIsAcceptable is true for sensor1, so the zone should not be
574 // thrown into failsafe mode.
575 EXPECT_FALSE(zone->getFailSafeMode());
576
577 // Do the same thing, but for the opposite sensors: r1 is good,
578 // but r2 is set to some time in the past.
579 r1.updated = std::chrono::high_resolution_clock::now();
580 r2.updated -= std::chrono::seconds(3);
581
582 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
583 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
584 zone->updateSensors();
585
586 // Now, the zone should be in failsafe mode, because sensor2 does not
587 // have MissingIsAcceptable set true, it is still subject to failsafe.
588 EXPECT_TRUE(zone->getFailSafeMode());
589
590 r1.updated = std::chrono::high_resolution_clock::now();
591 r2.updated = std::chrono::high_resolution_clock::now();
592
593 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
594 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
595 zone->updateSensors();
596
597 // The failsafe mode should cease, as both sensors are good again.
598 EXPECT_FALSE(zone->getFailSafeMode());
599}
600
Will Liangded0ab52019-05-15 17:10:06 +0800601TEST_F(PidZoneTest, FanInputTest_FailsafeToValid_ReadsSensors)
602{
603 // This will add a couple fan inputs, and verify the values are cached.
604
605 std::string name1 = "fan1";
606 int64_t timeout = 2;
607
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400608 std::unique_ptr<Sensor> sensor1 =
609 std::make_unique<SensorMock>(name1, timeout);
Will Liangded0ab52019-05-15 17:10:06 +0800610 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
611
612 std::string name2 = "fan2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400613 std::unique_ptr<Sensor> sensor2 =
614 std::make_unique<SensorMock>(name2, timeout);
Will Liangded0ab52019-05-15 17:10:06 +0800615 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
616
617 std::string type = "unchecked";
618 mgr.addSensor(type, name1, std::move(sensor1));
619 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
620 mgr.addSensor(type, name2, std::move(sensor2));
621 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
622
623 // Now that the sensors exist, add them to the zone.
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800624 zone->addFanInput(name1, false);
625 zone->addFanInput(name2, false);
Will Liangded0ab52019-05-15 17:10:06 +0800626
627 // Initialize Zone
628 zone->initializeCache();
629
630 // Verify now in failsafe mode.
631 EXPECT_TRUE(zone->getFailSafeMode());
632
633 ReadReturn r1;
634 r1.value = 10.0;
635 r1.updated = std::chrono::high_resolution_clock::now();
636 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
637
638 ReadReturn r2;
639 r2.value = 11.0;
640 r2.updated = std::chrono::high_resolution_clock::now();
641 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
642
643 // Method under test will read through each fan sensor for the zone and
644 // cache the values.
645 zone->updateFanTelemetry();
646
647 // We should no longer be in failsafe mode.
648 EXPECT_FALSE(zone->getFailSafeMode());
649
650 EXPECT_EQ(r1.value, zone->getCachedValue(name1));
651 EXPECT_EQ(r2.value, zone->getCachedValue(name2));
652}
653
654TEST_F(PidZoneTest, FanInputTest_ValueTimeoutEntersFailSafeMode)
655{
656 // This will add a couple fan inputs, and verify the values are cached.
657
658 std::string name1 = "fan1";
659 int64_t timeout = 2;
660
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400661 std::unique_ptr<Sensor> sensor1 =
662 std::make_unique<SensorMock>(name1, timeout);
Will Liangded0ab52019-05-15 17:10:06 +0800663 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
664
665 std::string name2 = "fan2";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400666 std::unique_ptr<Sensor> sensor2 =
667 std::make_unique<SensorMock>(name2, timeout);
Will Liangded0ab52019-05-15 17:10:06 +0800668 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
669
670 std::string type = "unchecked";
671 mgr.addSensor(type, name1, std::move(sensor1));
672 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
673 mgr.addSensor(type, name2, std::move(sensor2));
674 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
675
676 // Now that the sensors exist, add them to the zone.
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800677 zone->addFanInput(name1, false);
678 zone->addFanInput(name2, false);
Will Liangded0ab52019-05-15 17:10:06 +0800679
680 // Initialize Zone
681 zone->initializeCache();
682
683 // Verify now in failsafe mode.
684 EXPECT_TRUE(zone->getFailSafeMode());
685
686 ReadReturn r1;
687 r1.value = 10.0;
688 r1.updated = std::chrono::high_resolution_clock::now();
689 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
690
691 ReadReturn r2;
692 r2.value = 11.0;
693 r2.updated = std::chrono::high_resolution_clock::now();
694 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
695
696 // Method under test will read through each fan sensor for the zone and
697 // cache the values.
698 zone->updateFanTelemetry();
699
700 // We should no longer be in failsafe mode.
701 EXPECT_FALSE(zone->getFailSafeMode());
702
703 r1.updated -= std::chrono::seconds(3);
704 r2.updated = std::chrono::high_resolution_clock::now();
705
706 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
707 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
708
709 zone->updateFanTelemetry();
710 EXPECT_TRUE(zone->getFailSafeMode());
711}
712
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700713TEST_F(PidZoneTest, GetSensorTest_ReturnsExpected)
714{
Patrick Venturea58197c2018-06-11 15:29:45 -0700715 // One can grab a sensor from the manager through the zone.
716
717 int64_t timeout = 1;
718
719 std::string name1 = "temp1";
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400720 std::unique_ptr<Sensor> sensor1 =
721 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700722 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700723
724 std::string type = "unchecked";
725 mgr.addSensor(type, name1, std::move(sensor1));
726 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
727
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800728 zone->addThermalInput(name1, false);
Patrick Venturea58197c2018-06-11 15:29:45 -0700729
730 // Verify method under test returns the pointer we expect.
731 EXPECT_EQ(mgr.getSensor(name1), zone->getSensor(name1));
732}
733
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700734TEST_F(PidZoneTest, AddThermalPIDTest_VerifiesThermalPIDsProcessed)
735{
Patrick Venturea58197c2018-06-11 15:29:45 -0700736 // Tests adding a thermal PID controller to the zone, and verifies it's
737 // touched during processing.
738
739 std::unique_ptr<PIDController> tpid =
740 std::make_unique<ControllerMock>("thermal1", zone.get());
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700741 ControllerMock* tmock = reinterpret_cast<ControllerMock*>(tpid.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700742
743 // Access the internal pid configuration to clear it out (unrelated to the
744 // test).
Harvey Wu1b3b7302024-10-04 16:49:46 +0800745 [[maybe_unused]] ec::pid_info_t* info = tpid->getPIDInfo();
Patrick Venturea58197c2018-06-11 15:29:45 -0700746
747 zone->addThermalPID(std::move(tpid));
748
Patrick Venture563a3562018-10-30 09:31:26 -0700749 EXPECT_CALL(*tmock, setptProc()).WillOnce(Return(10.0));
750 EXPECT_CALL(*tmock, inputProc()).WillOnce(Return(11.0));
751 EXPECT_CALL(*tmock, outputProc(_));
Patrick Venturea58197c2018-06-11 15:29:45 -0700752
753 // Method under test will, for each thermal PID, call setpt, input, and
754 // output.
Patrick Venture563a3562018-10-30 09:31:26 -0700755 zone->processThermals();
Patrick Venturea58197c2018-06-11 15:29:45 -0700756}
757
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700758TEST_F(PidZoneTest, AddFanPIDTest_VerifiesFanPIDsProcessed)
759{
Patrick Venturea58197c2018-06-11 15:29:45 -0700760 // Tests adding a fan PID controller to the zone, and verifies it's
761 // touched during processing.
762
763 std::unique_ptr<PIDController> tpid =
764 std::make_unique<ControllerMock>("fan1", zone.get());
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700765 ControllerMock* tmock = reinterpret_cast<ControllerMock*>(tpid.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700766
767 // Access the internal pid configuration to clear it out (unrelated to the
768 // test).
Harvey Wu1b3b7302024-10-04 16:49:46 +0800769 [[maybe_unused]] ec::pid_info_t* info = tpid->getPIDInfo();
Patrick Venturea58197c2018-06-11 15:29:45 -0700770
771 zone->addFanPID(std::move(tpid));
772
Patrick Venture563a3562018-10-30 09:31:26 -0700773 EXPECT_CALL(*tmock, setptProc()).WillOnce(Return(10.0));
774 EXPECT_CALL(*tmock, inputProc()).WillOnce(Return(11.0));
775 EXPECT_CALL(*tmock, outputProc(_));
Patrick Venturea58197c2018-06-11 15:29:45 -0700776
777 // Method under test will, for each fan PID, call setpt, input, and output.
Patrick Venture563a3562018-10-30 09:31:26 -0700778 zone->processFans();
Patrick Venturea58197c2018-06-11 15:29:45 -0700779}
780
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700781TEST_F(PidZoneTest, ManualModeDbusTest_VerifySetManualBehavesAsExpected)
782{
Patrick Venturea58197c2018-06-11 15:29:45 -0700783 // The manual(bool) method is inherited from the dbus mode interface.
784
785 // Verifies that someone doesn't remove the internal call to the dbus
786 // object from which we're inheriting.
787 EXPECT_CALL(sdbus_mock_mode,
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700788 sd_bus_emit_properties_changed_strv(
789 IsNull(), StrEq(objPath), StrEq(modeInterface), NotNull()))
Harvey.Wua1ae4fa2022-10-28 17:38:35 +0800790 .WillOnce(Invoke(
791 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
792 [[maybe_unused]] const char* interface, const char** names) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400793 EXPECT_STREQ("Manual", names[0]);
794 return 0;
795 }));
Patrick Venturea58197c2018-06-11 15:29:45 -0700796
797 // Method under test will set the manual mode to true and broadcast this
798 // change on dbus.
799 zone->manual(true);
800 EXPECT_TRUE(zone->getManualMode());
801}
802
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700803TEST_F(PidZoneTest, FailsafeDbusTest_VerifiesReturnsExpected)
804{
Patrick Venturea58197c2018-06-11 15:29:45 -0700805 // This property is implemented by us as read-only, such that trying to
806 // write to it will have no effect.
807 EXPECT_EQ(zone->failSafe(), zone->getFailSafeMode());
808}
Patrick Venturea0764872020-08-08 07:48:43 -0700809
810} // namespace
811} // namespace pid_control