131058fd3SJosh Lehan #include "conf.hpp"
2de74542cSJosh Lehan #include "pid/ec/logging.hpp"
3da4a5dd1SPatrick Venture #include "pid/ec/pid.hpp"
43349ef20SPatrick Venture #include "pid/thermalcontroller.hpp"
5da4a5dd1SPatrick Venture #include "test/zone_mock.hpp"
63349ef20SPatrick Venture
73349ef20SPatrick Venture #include <string>
83349ef20SPatrick Venture #include <vector>
93349ef20SPatrick Venture
10da4a5dd1SPatrick Venture #include <gmock/gmock.h>
11da4a5dd1SPatrick Venture #include <gtest/gtest.h>
123349ef20SPatrick Venture
13a076487aSPatrick Venture namespace pid_control
14a076487aSPatrick Venture {
15a076487aSPatrick Venture namespace
16a076487aSPatrick Venture {
17a076487aSPatrick Venture
18572c43daSJames Feist using ::testing::_;
193349ef20SPatrick Venture using ::testing::Return;
203349ef20SPatrick Venture using ::testing::StrEq;
213349ef20SPatrick Venture
TEST(ThermalControllerTest,BoringFactoryTest)22da4a5dd1SPatrick Venture TEST(ThermalControllerTest, BoringFactoryTest)
23da4a5dd1SPatrick Venture {
243349ef20SPatrick Venture // Verifies building a ThermalPIDController with the factory works as
253349ef20SPatrick Venture // expected in the boring (uninteresting) case.
263349ef20SPatrick Venture
273349ef20SPatrick Venture ZoneMock z;
283349ef20SPatrick Venture
2931058fd3SJosh Lehan std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
305f59c0fdSPatrick Venture double setpoint = 10.0;
313349ef20SPatrick Venture ec::pidinfo initial;
323349ef20SPatrick Venture
33563a356fSPatrick Venture std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
34734f9535SJames Feist &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
353349ef20SPatrick Venture // Success
363349ef20SPatrick Venture EXPECT_FALSE(p == nullptr);
373349ef20SPatrick Venture }
383349ef20SPatrick Venture
TEST(ThermalControllerTest,VerifyFactoryFailsWithZeroInputs)39da4a5dd1SPatrick Venture TEST(ThermalControllerTest, VerifyFactoryFailsWithZeroInputs)
40da4a5dd1SPatrick Venture {
413349ef20SPatrick Venture // A thermal controller needs at least one input.
423349ef20SPatrick Venture
433349ef20SPatrick Venture ZoneMock z;
443349ef20SPatrick Venture
4531058fd3SJosh Lehan std::vector<pid_control::conf::SensorInput> inputs = {};
465f59c0fdSPatrick Venture double setpoint = 10.0;
473349ef20SPatrick Venture ec::pidinfo initial;
48734f9535SJames Feist std::unique_ptr<PIDController> p;
49734f9535SJames Feist EXPECT_THROW(
50da4a5dd1SPatrick Venture {
51734f9535SJames Feist p = ThermalController::createThermalPid(
52734f9535SJames Feist &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
53734f9535SJames Feist },
54734f9535SJames Feist std::exception);
553349ef20SPatrick Venture EXPECT_TRUE(p == nullptr);
563349ef20SPatrick Venture }
573349ef20SPatrick Venture
TEST(ThermalControllerTest,InputProc_BehavesAsExpected)58da4a5dd1SPatrick Venture TEST(ThermalControllerTest, InputProc_BehavesAsExpected)
59da4a5dd1SPatrick Venture {
60563a356fSPatrick Venture // This test just verifies inputProc behaves as expected.
613349ef20SPatrick Venture
623349ef20SPatrick Venture ZoneMock z;
633349ef20SPatrick Venture
6431058fd3SJosh Lehan std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
655f59c0fdSPatrick Venture double setpoint = 10.0;
663349ef20SPatrick Venture ec::pidinfo initial;
673349ef20SPatrick Venture
68563a356fSPatrick Venture std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
69734f9535SJames Feist &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
703349ef20SPatrick Venture EXPECT_FALSE(p == nullptr);
713349ef20SPatrick Venture
723349ef20SPatrick Venture EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0));
733349ef20SPatrick Venture
74563a356fSPatrick Venture EXPECT_EQ(5.0, p->inputProc());
753349ef20SPatrick Venture }
763349ef20SPatrick Venture
TEST(ThermalControllerTest,SetPtProc_BehavesAsExpected)77da4a5dd1SPatrick Venture TEST(ThermalControllerTest, SetPtProc_BehavesAsExpected)
78da4a5dd1SPatrick Venture {
79563a356fSPatrick Venture // This test just verifies inputProc behaves as expected.
803349ef20SPatrick Venture
813349ef20SPatrick Venture ZoneMock z;
823349ef20SPatrick Venture
8331058fd3SJosh Lehan std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
845f59c0fdSPatrick Venture double setpoint = 10.0;
853349ef20SPatrick Venture ec::pidinfo initial;
863349ef20SPatrick Venture
87563a356fSPatrick Venture std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
88734f9535SJames Feist &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
893349ef20SPatrick Venture EXPECT_FALSE(p == nullptr);
903349ef20SPatrick Venture
91563a356fSPatrick Venture EXPECT_EQ(setpoint, p->setptProc());
923349ef20SPatrick Venture }
933349ef20SPatrick Venture
TEST(ThermalControllerTest,OutputProc_BehavesAsExpected)94da4a5dd1SPatrick Venture TEST(ThermalControllerTest, OutputProc_BehavesAsExpected)
95da4a5dd1SPatrick Venture {
96734f9535SJames Feist // This test just verifies outputProc behaves as expected.
973349ef20SPatrick Venture
983349ef20SPatrick Venture ZoneMock z;
993349ef20SPatrick Venture
10031058fd3SJosh Lehan std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
1015f59c0fdSPatrick Venture double setpoint = 10.0;
1023349ef20SPatrick Venture ec::pidinfo initial;
1033349ef20SPatrick Venture
104563a356fSPatrick Venture std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
105734f9535SJames Feist &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
1063349ef20SPatrick Venture EXPECT_FALSE(p == nullptr);
1073349ef20SPatrick Venture
1085f59c0fdSPatrick Venture double value = 90.0;
109ccc8bb62SNirav Shah EXPECT_CALL(z, addSetPoint(value, "therm1"));
1103349ef20SPatrick Venture
111563a356fSPatrick Venture p->outputProc(value);
1123349ef20SPatrick Venture }
113734f9535SJames Feist
TEST(ThermalControllerTest,InputProc_MultipleInputsAbsolute)114734f9535SJames Feist TEST(ThermalControllerTest, InputProc_MultipleInputsAbsolute)
115734f9535SJames Feist {
116734f9535SJames Feist // This test verifies inputProc behaves as expected with multiple absolute
117734f9535SJames Feist // inputs.
118734f9535SJames Feist
119734f9535SJames Feist ZoneMock z;
120734f9535SJames Feist
121*bd63bcacSPatrick Williams std::vector<pid_control::conf::SensorInput> inputs = {
122*bd63bcacSPatrick Williams {"fleeting0"}, {"fleeting1"}};
123734f9535SJames Feist double setpoint = 10.0;
124734f9535SJames Feist ec::pidinfo initial;
125734f9535SJames Feist
126734f9535SJames Feist std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
127734f9535SJames Feist &z, "therm1", inputs, setpoint, initial, ThermalType::absolute);
128734f9535SJames Feist EXPECT_FALSE(p == nullptr);
129734f9535SJames Feist
130734f9535SJames Feist EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0));
131734f9535SJames Feist EXPECT_CALL(z, getCachedValue(StrEq("fleeting1"))).WillOnce(Return(10.0));
132734f9535SJames Feist
133734f9535SJames Feist EXPECT_EQ(10.0, p->inputProc());
134734f9535SJames Feist }
135734f9535SJames Feist
TEST(ThermalControllerTest,InputProc_MultipleInputsMargin)136734f9535SJames Feist TEST(ThermalControllerTest, InputProc_MultipleInputsMargin)
137734f9535SJames Feist {
138734f9535SJames Feist // This test verifies inputProc behaves as expected with multiple margin
139734f9535SJames Feist // inputs.
140734f9535SJames Feist
141734f9535SJames Feist ZoneMock z;
142734f9535SJames Feist
143*bd63bcacSPatrick Williams std::vector<pid_control::conf::SensorInput> inputs = {
144*bd63bcacSPatrick Williams {"fleeting0"}, {"fleeting1"}};
145734f9535SJames Feist double setpoint = 10.0;
146734f9535SJames Feist ec::pidinfo initial;
147734f9535SJames Feist
148734f9535SJames Feist std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
149734f9535SJames Feist &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
150734f9535SJames Feist EXPECT_FALSE(p == nullptr);
151734f9535SJames Feist
152734f9535SJames Feist EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0));
153734f9535SJames Feist EXPECT_CALL(z, getCachedValue(StrEq("fleeting1"))).WillOnce(Return(10.0));
154734f9535SJames Feist
155734f9535SJames Feist EXPECT_EQ(5.0, p->inputProc());
156734f9535SJames Feist }
157572c43daSJames Feist
TEST(ThermalControllerTest,InputProc_MultipleInputsSummation)15823e22b90SJosh Lehan TEST(ThermalControllerTest, InputProc_MultipleInputsSummation)
15923e22b90SJosh Lehan {
16023e22b90SJosh Lehan // This test verifies inputProc behaves as expected with multiple summation
16123e22b90SJosh Lehan // inputs.
16223e22b90SJosh Lehan
16323e22b90SJosh Lehan ZoneMock z;
16423e22b90SJosh Lehan
165*bd63bcacSPatrick Williams std::vector<pid_control::conf::SensorInput> inputs = {
166*bd63bcacSPatrick Williams {"fleeting0"}, {"fleeting1"}};
16723e22b90SJosh Lehan double setpoint = 10.0;
16823e22b90SJosh Lehan ec::pidinfo initial;
16923e22b90SJosh Lehan
17023e22b90SJosh Lehan std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
17123e22b90SJosh Lehan &z, "therm1", inputs, setpoint, initial, ThermalType::summation);
17223e22b90SJosh Lehan EXPECT_FALSE(p == nullptr);
17323e22b90SJosh Lehan
17423e22b90SJosh Lehan EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0));
17523e22b90SJosh Lehan EXPECT_CALL(z, getCachedValue(StrEq("fleeting1"))).WillOnce(Return(10.0));
17623e22b90SJosh Lehan
17723e22b90SJosh Lehan EXPECT_EQ(15.0, p->inputProc());
17823e22b90SJosh Lehan }
17923e22b90SJosh Lehan
TEST(ThermalControllerTest,InputProc_MultipleInputsTempToMargin)18031058fd3SJosh Lehan TEST(ThermalControllerTest, InputProc_MultipleInputsTempToMargin)
18131058fd3SJosh Lehan {
18231058fd3SJosh Lehan // This test verifies inputProc behaves as expected with multiple margin
18331058fd3SJosh Lehan // inputs and TempToMargin in use.
18431058fd3SJosh Lehan
18531058fd3SJosh Lehan ZoneMock z;
18631058fd3SJosh Lehan
18731058fd3SJosh Lehan std::vector<pid_control::conf::SensorInput> inputs = {
18831058fd3SJosh Lehan {"absolute0", 85.0, true}, {"margin1"}};
18931058fd3SJosh Lehan double setpoint = 10.0;
19031058fd3SJosh Lehan ec::pidinfo initial;
19131058fd3SJosh Lehan
19231058fd3SJosh Lehan std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
19331058fd3SJosh Lehan &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
19431058fd3SJosh Lehan EXPECT_FALSE(p == nullptr);
19531058fd3SJosh Lehan
19631058fd3SJosh Lehan EXPECT_CALL(z, getCachedValue(StrEq("absolute0"))).WillOnce(Return(82.0));
19731058fd3SJosh Lehan EXPECT_CALL(z, getCachedValue(StrEq("margin1"))).WillOnce(Return(5.0));
19831058fd3SJosh Lehan
19931058fd3SJosh Lehan // 82 degrees temp, 85 degrees Tjmax => 3 degrees of safety margin
20031058fd3SJosh Lehan EXPECT_EQ(3.0, p->inputProc());
20131058fd3SJosh Lehan }
20231058fd3SJosh Lehan
TEST(ThermalControllerTest,NegHysteresis_BehavesAsExpected)203572c43daSJames Feist TEST(ThermalControllerTest, NegHysteresis_BehavesAsExpected)
204572c43daSJames Feist {
205572c43daSJames Feist // This test verifies Negative hysteresis behaves as expected by
206572c43daSJames Feist // crossing the setpoint and noticing readings don't change until past the
207572c43daSJames Feist // hysteresis value
208572c43daSJames Feist
209572c43daSJames Feist ZoneMock z;
210572c43daSJames Feist
21131058fd3SJosh Lehan std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
212572c43daSJames Feist double setpoint = 10.0;
213572c43daSJames Feist ec::pidinfo initial;
2149788963cSDelphine CC Chiu initial.checkHysterWithSetpt = false;
215572c43daSJames Feist initial.negativeHysteresis = 4.0;
216572c43daSJames Feist
217572c43daSJames Feist std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
218572c43daSJames Feist &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
219572c43daSJames Feist EXPECT_FALSE(p == nullptr);
220572c43daSJames Feist
221572c43daSJames Feist EXPECT_CALL(z, getCachedValue(StrEq("fleeting0")))
222572c43daSJames Feist .Times(3)
223572c43daSJames Feist .WillOnce(Return(12.0))
224572c43daSJames Feist .WillOnce(Return(9.0))
225572c43daSJames Feist .WillOnce(Return(7.0));
226572c43daSJames Feist
227ccc8bb62SNirav Shah EXPECT_CALL(z, addSetPoint(_, "therm1")).Times(3);
228572c43daSJames Feist
229572c43daSJames Feist std::vector<double> lastReadings = {12.0, 12.0, 7.0};
230572c43daSJames Feist for (auto& reading : lastReadings)
231572c43daSJames Feist {
232572c43daSJames Feist p->process();
233572c43daSJames Feist EXPECT_EQ(p->getLastInput(), reading);
234572c43daSJames Feist }
235572c43daSJames Feist }
236572c43daSJames Feist
TEST(ThermalControllerTest,PosHysteresis_BehavesAsExpected)237572c43daSJames Feist TEST(ThermalControllerTest, PosHysteresis_BehavesAsExpected)
238572c43daSJames Feist {
239572c43daSJames Feist // This test verifies Positive hysteresis behaves as expected by
240572c43daSJames Feist // crossing the setpoint and noticing readings don't change until past the
241572c43daSJames Feist // hysteresis value
242572c43daSJames Feist
243572c43daSJames Feist ZoneMock z;
244572c43daSJames Feist
24531058fd3SJosh Lehan std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
246572c43daSJames Feist double setpoint = 10.0;
247572c43daSJames Feist ec::pidinfo initial;
2489788963cSDelphine CC Chiu initial.checkHysterWithSetpt = false;
249572c43daSJames Feist initial.positiveHysteresis = 5.0;
250572c43daSJames Feist
251572c43daSJames Feist std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
252572c43daSJames Feist &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
253572c43daSJames Feist EXPECT_FALSE(p == nullptr);
254572c43daSJames Feist
255572c43daSJames Feist EXPECT_CALL(z, getCachedValue(StrEq("fleeting0")))
256572c43daSJames Feist .Times(3)
257572c43daSJames Feist .WillOnce(Return(8.0))
258572c43daSJames Feist .WillOnce(Return(13.0))
259572c43daSJames Feist .WillOnce(Return(14.0));
260572c43daSJames Feist
261ccc8bb62SNirav Shah EXPECT_CALL(z, addSetPoint(_, "therm1")).Times(3);
262572c43daSJames Feist
263572c43daSJames Feist std::vector<double> lastReadings = {8.0, 8.0, 14.0};
264572c43daSJames Feist for (auto& reading : lastReadings)
265572c43daSJames Feist {
266572c43daSJames Feist p->process();
267572c43daSJames Feist EXPECT_EQ(p->getLastInput(), reading);
268572c43daSJames Feist }
269572c43daSJames Feist }
270a076487aSPatrick Venture
271a076487aSPatrick Venture } // namespace
272a076487aSPatrick Venture } // namespace pid_control
273