blob: d7ae9eca548361c81156147dc3a6e742a1cae557 [file] [log] [blame]
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07001#include "pid/ec/pid.hpp"
Patrick Venturea58197c2018-06-11 15:29:45 -07002#include "pid/zone.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07003#include "sensors/manager.hpp"
4#include "test/controller_mock.hpp"
5#include "test/helpers.hpp"
6#include "test/sensor_mock.hpp"
Patrick Venturea58197c2018-06-11 15:29:45 -07007
Patrick Venturea83a3ec2020-08-04 09:52:05 -07008#include <sdbusplus/test/sdbus_mock.hpp>
9
Patrick Venturea58197c2018-06-11 15:29:45 -070010#include <chrono>
11#include <cstring>
Patrick Venturea58197c2018-06-11 15:29:45 -070012#include <vector>
13
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070014#include <gmock/gmock.h>
15#include <gtest/gtest.h>
Patrick Venturea58197c2018-06-11 15:29:45 -070016
Patrick Venturea0764872020-08-08 07:48:43 -070017namespace pid_control
18{
19namespace
20{
21
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070022using ::testing::_;
Patrick Venturea58197c2018-06-11 15:29:45 -070023using ::testing::IsNull;
24using ::testing::Return;
25using ::testing::StrEq;
Patrick Venturea58197c2018-06-11 15:29:45 -070026
27static std::string modeInterface = "xyz.openbmc_project.Control.Mode";
28
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070029namespace
30{
Patrick Venturea58197c2018-06-11 15:29:45 -070031
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070032TEST(PidZoneConstructorTest, BoringConstructorTest)
33{
Patrick Venturea58197c2018-06-11 15:29:45 -070034 // Build a PID Zone.
35
36 sdbusplus::SdBusMock sdbus_mock_passive, sdbus_mock_host, sdbus_mock_mode;
37 auto bus_mock_passive = sdbusplus::get_mocked_new(&sdbus_mock_passive);
38 auto bus_mock_host = sdbusplus::get_mocked_new(&sdbus_mock_host);
39 auto bus_mock_mode = sdbusplus::get_mocked_new(&sdbus_mock_mode);
40
41 EXPECT_CALL(sdbus_mock_host,
42 sd_bus_add_object_manager(
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070043 IsNull(), _, StrEq("/xyz/openbmc_project/extsensors")))
Patrick Venturea58197c2018-06-11 15:29:45 -070044 .WillOnce(Return(0));
45
James Feist1fe08952019-05-07 09:17:16 -070046 SensorManager m(bus_mock_passive, bus_mock_host);
Patrick Venturea58197c2018-06-11 15:29:45 -070047
48 bool defer = true;
Patrick Venturee2ec0f62018-09-04 12:30:27 -070049 const char* objPath = "/path/";
Patrick Venturea58197c2018-06-11 15:29:45 -070050 int64_t zone = 1;
James Feist3484bed2019-02-25 13:28:18 -080051 double minThermalOutput = 1000.0;
Patrick Venture5f59c0f2018-11-11 12:55:14 -080052 double failSafePercent = 0.75;
Patrick Venturea58197c2018-06-11 15:29:45 -070053
James Feist0709e2f2020-07-08 10:59:45 -070054 double d;
Patrick Venturea58197c2018-06-11 15:29:45 -070055 std::vector<std::string> properties;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070056 SetupDbusObject(&sdbus_mock_mode, defer, objPath, modeInterface, properties,
James Feist0709e2f2020-07-08 10:59:45 -070057 &d);
Patrick Venturea58197c2018-06-11 15:29:45 -070058
James Feist3484bed2019-02-25 13:28:18 -080059 PIDZone p(zone, minThermalOutput, failSafePercent, m, bus_mock_mode,
60 objPath, defer);
Patrick Venturea58197c2018-06-11 15:29:45 -070061 // Success.
62}
63
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070064} // namespace
Patrick Venturea58197c2018-06-11 15:29:45 -070065
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070066class PidZoneTest : public ::testing::Test
67{
68 protected:
69 PidZoneTest() :
70 property_index(), properties(), sdbus_mock_passive(), sdbus_mock_host(),
71 sdbus_mock_mode()
72 {
73 EXPECT_CALL(sdbus_mock_host,
74 sd_bus_add_object_manager(
75 IsNull(), _, StrEq("/xyz/openbmc_project/extsensors")))
76 .WillOnce(Return(0));
Patrick Venturea58197c2018-06-11 15:29:45 -070077
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070078 auto bus_mock_passive = sdbusplus::get_mocked_new(&sdbus_mock_passive);
79 auto bus_mock_host = sdbusplus::get_mocked_new(&sdbus_mock_host);
80 auto bus_mock_mode = sdbusplus::get_mocked_new(&sdbus_mock_mode);
Patrick Venturea58197c2018-06-11 15:29:45 -070081
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070082 // Compiler weirdly not happy about just instantiating mgr(...);
James Feist1fe08952019-05-07 09:17:16 -070083 SensorManager m(bus_mock_passive, bus_mock_host);
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070084 mgr = std::move(m);
Patrick Venturea58197c2018-06-11 15:29:45 -070085
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070086 SetupDbusObject(&sdbus_mock_mode, defer, objPath, modeInterface,
87 properties, &property_index);
Patrick Venturea58197c2018-06-11 15:29:45 -070088
James Feist3484bed2019-02-25 13:28:18 -080089 zone =
90 std::make_unique<PIDZone>(zoneId, minThermalOutput, failSafePercent,
91 mgr, bus_mock_mode, objPath, defer);
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070092 }
Patrick Venturea58197c2018-06-11 15:29:45 -070093
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070094 // unused
James Feist0709e2f2020-07-08 10:59:45 -070095 double property_index;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070096 std::vector<std::string> properties;
Patrick Venturea58197c2018-06-11 15:29:45 -070097
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070098 sdbusplus::SdBusMock sdbus_mock_passive;
99 sdbusplus::SdBusMock sdbus_mock_host;
100 sdbusplus::SdBusMock sdbus_mock_mode;
101 int64_t zoneId = 1;
James Feist3484bed2019-02-25 13:28:18 -0800102 double minThermalOutput = 1000.0;
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800103 double failSafePercent = 0.75;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700104 bool defer = true;
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700105 const char* objPath = "/path/";
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700106 SensorManager mgr;
Patrick Venturea58197c2018-06-11 15:29:45 -0700107
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700108 std::unique_ptr<PIDZone> zone;
Patrick Venturea58197c2018-06-11 15:29:45 -0700109};
110
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700111TEST_F(PidZoneTest, GetZoneId_ReturnsExpected)
112{
Patrick Venturea58197c2018-06-11 15:29:45 -0700113 // Verifies the zoneId returned is what we expect.
114
Patrick Venture0bbeaf82018-10-30 18:50:31 -0700115 EXPECT_EQ(zoneId, zone->getZoneID());
Patrick Venturea58197c2018-06-11 15:29:45 -0700116}
117
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700118TEST_F(PidZoneTest, GetAndSetManualModeTest_BehavesAsExpected)
119{
Patrick Venturea58197c2018-06-11 15:29:45 -0700120 // Verifies that the zone starts in manual mode. Verifies that one can set
121 // the mode.
122 EXPECT_FALSE(zone->getManualMode());
123
124 zone->setManualMode(true);
125 EXPECT_TRUE(zone->getManualMode());
126}
127
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700128TEST_F(PidZoneTest, RpmSetPoints_AddMaxClear_BehaveAsExpected)
129{
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700130 // Tests addSetPoint, clearSetPoints, determineMaxSetPointRequest
131 // and getMinThermalSetpoint.
Patrick Venturea58197c2018-06-11 15:29:45 -0700132
133 // At least one value must be above the minimum thermal setpoint used in
134 // the constructor otherwise it'll choose that value
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800135 std::vector<double> values = {100, 200, 300, 400, 500, 5000};
Patrick Venturea58197c2018-06-11 15:29:45 -0700136 for (auto v : values)
137 {
Patrick Venture9bbf3332019-07-16 10:50:37 -0700138 zone->addSetPoint(v);
Patrick Venturea58197c2018-06-11 15:29:45 -0700139 }
140
141 // This will pull the maximum RPM setpoint request.
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700142 zone->determineMaxSetPointRequest();
143 EXPECT_EQ(5000, zone->getMaxSetPointRequest());
Patrick Venturea58197c2018-06-11 15:29:45 -0700144
145 // Clear the values, so it'll choose the minimum thermal setpoint.
Patrick Venture9bbf3332019-07-16 10:50:37 -0700146 zone->clearSetPoints();
Patrick Venturea58197c2018-06-11 15:29:45 -0700147
148 // This will go through the RPM set point values and grab the maximum.
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700149 zone->determineMaxSetPointRequest();
150 EXPECT_EQ(zone->getMinThermalSetpoint(), zone->getMaxSetPointRequest());
Patrick Venturea58197c2018-06-11 15:29:45 -0700151}
152
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700153TEST_F(PidZoneTest, RpmSetPoints_AddBelowMinimum_BehavesAsExpected)
154{
Patrick Venturea58197c2018-06-11 15:29:45 -0700155 // Tests adding several RPM setpoints, however, they're all lower than the
Patrick Venture7280e272019-02-11 10:45:32 -0800156 // configured minimal thermal setpoint RPM value.
Patrick Venturea58197c2018-06-11 15:29:45 -0700157
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800158 std::vector<double> values = {100, 200, 300, 400, 500};
Patrick Venturea58197c2018-06-11 15:29:45 -0700159 for (auto v : values)
160 {
Patrick Venture9bbf3332019-07-16 10:50:37 -0700161 zone->addSetPoint(v);
Patrick Venturea58197c2018-06-11 15:29:45 -0700162 }
163
164 // This will pull the maximum RPM setpoint request.
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700165 zone->determineMaxSetPointRequest();
Patrick Venturea58197c2018-06-11 15:29:45 -0700166
167 // Verifies the value returned in the minimal thermal rpm set point.
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700168 EXPECT_EQ(zone->getMinThermalSetpoint(), zone->getMaxSetPointRequest());
Patrick Venturea58197c2018-06-11 15:29:45 -0700169}
170
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700171TEST_F(PidZoneTest, GetFailSafePercent_ReturnsExpected)
172{
Patrick Venturea58197c2018-06-11 15:29:45 -0700173 // Verify the value used to create the object is stored.
174 EXPECT_EQ(failSafePercent, zone->getFailSafePercent());
175}
176
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700177TEST_F(PidZoneTest, ThermalInputs_FailsafeToValid_ReadsSensors)
178{
Patrick Venturea58197c2018-06-11 15:29:45 -0700179 // This test will add a couple thermal inputs, and verify that the zone
180 // initializes into failsafe mode, and will read each sensor.
181
182 std::string name1 = "temp1";
183 int64_t timeout = 1;
184
185 std::unique_ptr<Sensor> sensor1 =
186 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700187 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700188
189 std::string name2 = "temp2";
190 std::unique_ptr<Sensor> sensor2 =
191 std::make_unique<SensorMock>(name2, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700192 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700193
194 std::string type = "unchecked";
195 mgr.addSensor(type, name1, std::move(sensor1));
196 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
197 mgr.addSensor(type, name2, std::move(sensor2));
198 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
199
200 // Now that the sensors exist, add them to the zone.
201 zone->addThermalInput(name1);
202 zone->addThermalInput(name2);
203
204 // Initialize Zone
205 zone->initializeCache();
206
207 // Verify now in failsafe mode.
208 EXPECT_TRUE(zone->getFailSafeMode());
209
210 ReadReturn r1;
211 r1.value = 10.0;
212 r1.updated = std::chrono::high_resolution_clock::now();
213 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
214
215 ReadReturn r2;
216 r2.value = 11.0;
217 r2.updated = std::chrono::high_resolution_clock::now();
218 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
219
220 // Read the sensors, this will put the values into the cache.
221 zone->updateSensors();
222
223 // We should no longer be in failsafe mode.
224 EXPECT_FALSE(zone->getFailSafeMode());
225
226 EXPECT_EQ(r1.value, zone->getCachedValue(name1));
227 EXPECT_EQ(r2.value, zone->getCachedValue(name2));
228}
229
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700230TEST_F(PidZoneTest, FanInputTest_VerifiesFanValuesCached)
231{
Patrick Venturea58197c2018-06-11 15:29:45 -0700232 // This will add a couple fan inputs, and verify the values are cached.
233
234 std::string name1 = "fan1";
235 int64_t timeout = 2;
236
237 std::unique_ptr<Sensor> sensor1 =
238 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700239 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700240
241 std::string name2 = "fan2";
242 std::unique_ptr<Sensor> sensor2 =
243 std::make_unique<SensorMock>(name2, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700244 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700245
246 std::string type = "unchecked";
247 mgr.addSensor(type, name1, std::move(sensor1));
248 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
249 mgr.addSensor(type, name2, std::move(sensor2));
250 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
251
252 // Now that the sensors exist, add them to the zone.
253 zone->addFanInput(name1);
254 zone->addFanInput(name2);
255
256 // Initialize Zone
257 zone->initializeCache();
258
259 ReadReturn r1;
260 r1.value = 10.0;
261 r1.updated = std::chrono::high_resolution_clock::now();
262 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
263
264 ReadReturn r2;
265 r2.value = 11.0;
266 r2.updated = std::chrono::high_resolution_clock::now();
267 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
268
269 // Method under test will read through each fan sensor for the zone and
270 // cache the values.
271 zone->updateFanTelemetry();
272
273 EXPECT_EQ(r1.value, zone->getCachedValue(name1));
274 EXPECT_EQ(r2.value, zone->getCachedValue(name2));
275}
276
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700277TEST_F(PidZoneTest, ThermalInput_ValueTimeoutEntersFailSafeMode)
278{
Patrick Venturea58197c2018-06-11 15:29:45 -0700279 // On the second updateSensors call, the updated timestamp will be beyond
280 // the timeout limit.
281
282 int64_t timeout = 1;
283
284 std::string name1 = "temp1";
285 std::unique_ptr<Sensor> sensor1 =
286 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700287 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700288
289 std::string name2 = "temp2";
290 std::unique_ptr<Sensor> sensor2 =
291 std::make_unique<SensorMock>(name2, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700292 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700293
294 std::string type = "unchecked";
295 mgr.addSensor(type, name1, std::move(sensor1));
296 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
297 mgr.addSensor(type, name2, std::move(sensor2));
298 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
299
300 zone->addThermalInput(name1);
301 zone->addThermalInput(name2);
302
303 // Initialize Zone
304 zone->initializeCache();
305
306 // Verify now in failsafe mode.
307 EXPECT_TRUE(zone->getFailSafeMode());
308
309 ReadReturn r1;
310 r1.value = 10.0;
311 r1.updated = std::chrono::high_resolution_clock::now();
312 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
313
314 ReadReturn r2;
315 r2.value = 11.0;
316 r2.updated = std::chrono::high_resolution_clock::now();
317 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
318
319 zone->updateSensors();
320 EXPECT_FALSE(zone->getFailSafeMode());
321
322 // Ok, so we're not in failsafe mode, so let's set updated to the past.
323 // sensor1 will have an updated field older than its timeout value, but
324 // sensor2 will be fine. :D
325 r1.updated -= std::chrono::seconds(3);
326 r2.updated = std::chrono::high_resolution_clock::now();
327
328 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
329 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
330
331 // Method under test will read each sensor. One sensor's value is older
332 // than the timeout for that sensor and this triggers failsafe mode.
333 zone->updateSensors();
334 EXPECT_TRUE(zone->getFailSafeMode());
335}
336
Will Liangded0ab52019-05-15 17:10:06 +0800337TEST_F(PidZoneTest, FanInputTest_FailsafeToValid_ReadsSensors)
338{
339 // This will add a couple fan inputs, and verify the values are cached.
340
341 std::string name1 = "fan1";
342 int64_t timeout = 2;
343
344 std::unique_ptr<Sensor> sensor1 =
345 std::make_unique<SensorMock>(name1, timeout);
346 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
347
348 std::string name2 = "fan2";
349 std::unique_ptr<Sensor> sensor2 =
350 std::make_unique<SensorMock>(name2, timeout);
351 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
352
353 std::string type = "unchecked";
354 mgr.addSensor(type, name1, std::move(sensor1));
355 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
356 mgr.addSensor(type, name2, std::move(sensor2));
357 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
358
359 // Now that the sensors exist, add them to the zone.
360 zone->addFanInput(name1);
361 zone->addFanInput(name2);
362
363 // Initialize Zone
364 zone->initializeCache();
365
366 // Verify now in failsafe mode.
367 EXPECT_TRUE(zone->getFailSafeMode());
368
369 ReadReturn r1;
370 r1.value = 10.0;
371 r1.updated = std::chrono::high_resolution_clock::now();
372 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
373
374 ReadReturn r2;
375 r2.value = 11.0;
376 r2.updated = std::chrono::high_resolution_clock::now();
377 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
378
379 // Method under test will read through each fan sensor for the zone and
380 // cache the values.
381 zone->updateFanTelemetry();
382
383 // We should no longer be in failsafe mode.
384 EXPECT_FALSE(zone->getFailSafeMode());
385
386 EXPECT_EQ(r1.value, zone->getCachedValue(name1));
387 EXPECT_EQ(r2.value, zone->getCachedValue(name2));
388}
389
390TEST_F(PidZoneTest, FanInputTest_ValueTimeoutEntersFailSafeMode)
391{
392 // This will add a couple fan inputs, and verify the values are cached.
393
394 std::string name1 = "fan1";
395 int64_t timeout = 2;
396
397 std::unique_ptr<Sensor> sensor1 =
398 std::make_unique<SensorMock>(name1, timeout);
399 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
400
401 std::string name2 = "fan2";
402 std::unique_ptr<Sensor> sensor2 =
403 std::make_unique<SensorMock>(name2, timeout);
404 SensorMock* sensor_ptr2 = reinterpret_cast<SensorMock*>(sensor2.get());
405
406 std::string type = "unchecked";
407 mgr.addSensor(type, name1, std::move(sensor1));
408 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
409 mgr.addSensor(type, name2, std::move(sensor2));
410 EXPECT_EQ(mgr.getSensor(name2), sensor_ptr2);
411
412 // Now that the sensors exist, add them to the zone.
413 zone->addFanInput(name1);
414 zone->addFanInput(name2);
415
416 // Initialize Zone
417 zone->initializeCache();
418
419 // Verify now in failsafe mode.
420 EXPECT_TRUE(zone->getFailSafeMode());
421
422 ReadReturn r1;
423 r1.value = 10.0;
424 r1.updated = std::chrono::high_resolution_clock::now();
425 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
426
427 ReadReturn r2;
428 r2.value = 11.0;
429 r2.updated = std::chrono::high_resolution_clock::now();
430 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
431
432 // Method under test will read through each fan sensor for the zone and
433 // cache the values.
434 zone->updateFanTelemetry();
435
436 // We should no longer be in failsafe mode.
437 EXPECT_FALSE(zone->getFailSafeMode());
438
439 r1.updated -= std::chrono::seconds(3);
440 r2.updated = std::chrono::high_resolution_clock::now();
441
442 EXPECT_CALL(*sensor_ptr1, read()).WillOnce(Return(r1));
443 EXPECT_CALL(*sensor_ptr2, read()).WillOnce(Return(r2));
444
445 zone->updateFanTelemetry();
446 EXPECT_TRUE(zone->getFailSafeMode());
447}
448
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700449TEST_F(PidZoneTest, GetSensorTest_ReturnsExpected)
450{
Patrick Venturea58197c2018-06-11 15:29:45 -0700451 // One can grab a sensor from the manager through the zone.
452
453 int64_t timeout = 1;
454
455 std::string name1 = "temp1";
456 std::unique_ptr<Sensor> sensor1 =
457 std::make_unique<SensorMock>(name1, timeout);
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700458 SensorMock* sensor_ptr1 = reinterpret_cast<SensorMock*>(sensor1.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700459
460 std::string type = "unchecked";
461 mgr.addSensor(type, name1, std::move(sensor1));
462 EXPECT_EQ(mgr.getSensor(name1), sensor_ptr1);
463
464 zone->addThermalInput(name1);
465
466 // Verify method under test returns the pointer we expect.
467 EXPECT_EQ(mgr.getSensor(name1), zone->getSensor(name1));
468}
469
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700470TEST_F(PidZoneTest, AddThermalPIDTest_VerifiesThermalPIDsProcessed)
471{
Patrick Venturea58197c2018-06-11 15:29:45 -0700472 // Tests adding a thermal PID controller to the zone, and verifies it's
473 // touched during processing.
474
475 std::unique_ptr<PIDController> tpid =
476 std::make_unique<ControllerMock>("thermal1", zone.get());
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700477 ControllerMock* tmock = reinterpret_cast<ControllerMock*>(tpid.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700478
479 // Access the internal pid configuration to clear it out (unrelated to the
480 // test).
Patrick Venture563a3562018-10-30 09:31:26 -0700481 ec::pid_info_t* info = tpid->getPIDInfo();
Patrick Venturea58197c2018-06-11 15:29:45 -0700482 std::memset(info, 0x00, sizeof(ec::pid_info_t));
483
484 zone->addThermalPID(std::move(tpid));
485
Patrick Venture563a3562018-10-30 09:31:26 -0700486 EXPECT_CALL(*tmock, setptProc()).WillOnce(Return(10.0));
487 EXPECT_CALL(*tmock, inputProc()).WillOnce(Return(11.0));
488 EXPECT_CALL(*tmock, outputProc(_));
Patrick Venturea58197c2018-06-11 15:29:45 -0700489
490 // Method under test will, for each thermal PID, call setpt, input, and
491 // output.
Patrick Venture563a3562018-10-30 09:31:26 -0700492 zone->processThermals();
Patrick Venturea58197c2018-06-11 15:29:45 -0700493}
494
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700495TEST_F(PidZoneTest, AddFanPIDTest_VerifiesFanPIDsProcessed)
496{
Patrick Venturea58197c2018-06-11 15:29:45 -0700497 // Tests adding a fan PID controller to the zone, and verifies it's
498 // touched during processing.
499
500 std::unique_ptr<PIDController> tpid =
501 std::make_unique<ControllerMock>("fan1", zone.get());
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700502 ControllerMock* tmock = reinterpret_cast<ControllerMock*>(tpid.get());
Patrick Venturea58197c2018-06-11 15:29:45 -0700503
504 // Access the internal pid configuration to clear it out (unrelated to the
505 // test).
Patrick Venture563a3562018-10-30 09:31:26 -0700506 ec::pid_info_t* info = tpid->getPIDInfo();
Patrick Venturea58197c2018-06-11 15:29:45 -0700507 std::memset(info, 0x00, sizeof(ec::pid_info_t));
508
509 zone->addFanPID(std::move(tpid));
510
Patrick Venture563a3562018-10-30 09:31:26 -0700511 EXPECT_CALL(*tmock, setptProc()).WillOnce(Return(10.0));
512 EXPECT_CALL(*tmock, inputProc()).WillOnce(Return(11.0));
513 EXPECT_CALL(*tmock, outputProc(_));
Patrick Venturea58197c2018-06-11 15:29:45 -0700514
515 // Method under test will, for each fan PID, call setpt, input, and output.
Patrick Venture563a3562018-10-30 09:31:26 -0700516 zone->processFans();
Patrick Venturea58197c2018-06-11 15:29:45 -0700517}
518
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700519TEST_F(PidZoneTest, ManualModeDbusTest_VerifySetManualBehavesAsExpected)
520{
Patrick Venturea58197c2018-06-11 15:29:45 -0700521 // The manual(bool) method is inherited from the dbus mode interface.
522
523 // Verifies that someone doesn't remove the internal call to the dbus
524 // object from which we're inheriting.
525 EXPECT_CALL(sdbus_mock_mode,
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700526 sd_bus_emit_properties_changed_strv(
527 IsNull(), StrEq(objPath), StrEq(modeInterface), NotNull()))
Patrick Venturee2ec0f62018-09-04 12:30:27 -0700528 .WillOnce(Invoke([&](sd_bus* bus, const char* path,
529 const char* interface, char** names) {
Patrick Venturea58197c2018-06-11 15:29:45 -0700530 EXPECT_STREQ("Manual", names[0]);
531 return 0;
532 }));
533
534 // Method under test will set the manual mode to true and broadcast this
535 // change on dbus.
536 zone->manual(true);
537 EXPECT_TRUE(zone->getManualMode());
538}
539
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700540TEST_F(PidZoneTest, FailsafeDbusTest_VerifiesReturnsExpected)
541{
Patrick Venturea58197c2018-06-11 15:29:45 -0700542 // This property is implemented by us as read-only, such that trying to
543 // write to it will have no effect.
544 EXPECT_EQ(zone->failSafe(), zone->getFailSafeMode());
545}
Patrick Venturea0764872020-08-08 07:48:43 -0700546
547} // namespace
548} // namespace pid_control