blob: 7aee1e10c2c565574222c0d73d9e9018ab8317b4 [file] [log] [blame]
Josh Lehan31058fd2023-01-13 11:06:16 -08001#include "conf.hpp"
Josh Lehande745422020-11-07 02:14:09 -08002#include "pid/ec/logging.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07003#include "pid/ec/pid.hpp"
Patrick Venture3349ef22018-06-12 14:09:29 -07004#include "pid/thermalcontroller.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07005#include "test/zone_mock.hpp"
Patrick Venture3349ef22018-06-12 14:09:29 -07006
Patrick Venture3349ef22018-06-12 14:09:29 -07007#include <string>
8#include <vector>
9
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070010#include <gmock/gmock.h>
11#include <gtest/gtest.h>
Patrick Venture3349ef22018-06-12 14:09:29 -070012
Patrick Venturea0764872020-08-08 07:48:43 -070013namespace pid_control
14{
15namespace
16{
17
James Feist572c43d2019-01-31 15:52:22 -080018using ::testing::_;
Patrick Venture3349ef22018-06-12 14:09:29 -070019using ::testing::Return;
20using ::testing::StrEq;
21
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070022TEST(ThermalControllerTest, BoringFactoryTest)
23{
Patrick Venture3349ef22018-06-12 14:09:29 -070024 // Verifies building a ThermalPIDController with the factory works as
25 // expected in the boring (uninteresting) case.
26
27 ZoneMock z;
28
Josh Lehan31058fd2023-01-13 11:06:16 -080029 std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
Patrick Venture5f59c0f2018-11-11 12:55:14 -080030 double setpoint = 10.0;
Patrick Venture3349ef22018-06-12 14:09:29 -070031 ec::pidinfo initial;
32
Patrick Venture563a3562018-10-30 09:31:26 -070033 std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
James Feist734f9532018-11-15 12:13:18 -080034 &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
Patrick Venture3349ef22018-06-12 14:09:29 -070035 // Success
36 EXPECT_FALSE(p == nullptr);
37}
38
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070039TEST(ThermalControllerTest, VerifyFactoryFailsWithZeroInputs)
40{
Patrick Venture3349ef22018-06-12 14:09:29 -070041 // A thermal controller needs at least one input.
42
43 ZoneMock z;
44
Josh Lehan31058fd2023-01-13 11:06:16 -080045 std::vector<pid_control::conf::SensorInput> inputs = {};
Patrick Venture5f59c0f2018-11-11 12:55:14 -080046 double setpoint = 10.0;
Patrick Venture3349ef22018-06-12 14:09:29 -070047 ec::pidinfo initial;
James Feist734f9532018-11-15 12:13:18 -080048 std::unique_ptr<PIDController> p;
49 EXPECT_THROW(
50 {
51 p = ThermalController::createThermalPid(
52 &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
53 },
54 std::exception);
Patrick Venture3349ef22018-06-12 14:09:29 -070055 EXPECT_TRUE(p == nullptr);
56}
57
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070058TEST(ThermalControllerTest, InputProc_BehavesAsExpected)
59{
Patrick Venture563a3562018-10-30 09:31:26 -070060 // This test just verifies inputProc behaves as expected.
Patrick Venture3349ef22018-06-12 14:09:29 -070061
62 ZoneMock z;
63
Josh Lehan31058fd2023-01-13 11:06:16 -080064 std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
Patrick Venture5f59c0f2018-11-11 12:55:14 -080065 double setpoint = 10.0;
Patrick Venture3349ef22018-06-12 14:09:29 -070066 ec::pidinfo initial;
67
Patrick Venture563a3562018-10-30 09:31:26 -070068 std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
James Feist734f9532018-11-15 12:13:18 -080069 &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
Patrick Venture3349ef22018-06-12 14:09:29 -070070 EXPECT_FALSE(p == nullptr);
71
72 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0));
73
Patrick Venture563a3562018-10-30 09:31:26 -070074 EXPECT_EQ(5.0, p->inputProc());
Patrick Venture3349ef22018-06-12 14:09:29 -070075}
76
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070077TEST(ThermalControllerTest, SetPtProc_BehavesAsExpected)
78{
Patrick Venture563a3562018-10-30 09:31:26 -070079 // This test just verifies inputProc behaves as expected.
Patrick Venture3349ef22018-06-12 14:09:29 -070080
81 ZoneMock z;
82
Josh Lehan31058fd2023-01-13 11:06:16 -080083 std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
Patrick Venture5f59c0f2018-11-11 12:55:14 -080084 double setpoint = 10.0;
Patrick Venture3349ef22018-06-12 14:09:29 -070085 ec::pidinfo initial;
86
Patrick Venture563a3562018-10-30 09:31:26 -070087 std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
James Feist734f9532018-11-15 12:13:18 -080088 &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
Patrick Venture3349ef22018-06-12 14:09:29 -070089 EXPECT_FALSE(p == nullptr);
90
Patrick Venture563a3562018-10-30 09:31:26 -070091 EXPECT_EQ(setpoint, p->setptProc());
Patrick Venture3349ef22018-06-12 14:09:29 -070092}
93
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070094TEST(ThermalControllerTest, OutputProc_BehavesAsExpected)
95{
James Feist734f9532018-11-15 12:13:18 -080096 // This test just verifies outputProc behaves as expected.
Patrick Venture3349ef22018-06-12 14:09:29 -070097
98 ZoneMock z;
99
Josh Lehan31058fd2023-01-13 11:06:16 -0800100 std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800101 double setpoint = 10.0;
Patrick Venture3349ef22018-06-12 14:09:29 -0700102 ec::pidinfo initial;
103
Patrick Venture563a3562018-10-30 09:31:26 -0700104 std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
James Feist734f9532018-11-15 12:13:18 -0800105 &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
Patrick Venture3349ef22018-06-12 14:09:29 -0700106 EXPECT_FALSE(p == nullptr);
107
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800108 double value = 90.0;
Nirav Shahccc8bb62022-02-17 21:06:51 -0800109 EXPECT_CALL(z, addSetPoint(value, "therm1"));
Patrick Venture3349ef22018-06-12 14:09:29 -0700110
Patrick Venture563a3562018-10-30 09:31:26 -0700111 p->outputProc(value);
Patrick Venture3349ef22018-06-12 14:09:29 -0700112}
James Feist734f9532018-11-15 12:13:18 -0800113
114TEST(ThermalControllerTest, InputProc_MultipleInputsAbsolute)
115{
116 // This test verifies inputProc behaves as expected with multiple absolute
117 // inputs.
118
119 ZoneMock z;
120
Josh Lehan31058fd2023-01-13 11:06:16 -0800121 std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"},
122 {"fleeting1"}};
James Feist734f9532018-11-15 12:13:18 -0800123 double setpoint = 10.0;
124 ec::pidinfo initial;
125
126 std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
127 &z, "therm1", inputs, setpoint, initial, ThermalType::absolute);
128 EXPECT_FALSE(p == nullptr);
129
130 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0));
131 EXPECT_CALL(z, getCachedValue(StrEq("fleeting1"))).WillOnce(Return(10.0));
132
133 EXPECT_EQ(10.0, p->inputProc());
134}
135
136TEST(ThermalControllerTest, InputProc_MultipleInputsMargin)
137{
138 // This test verifies inputProc behaves as expected with multiple margin
139 // inputs.
140
141 ZoneMock z;
142
Josh Lehan31058fd2023-01-13 11:06:16 -0800143 std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"},
144 {"fleeting1"}};
James Feist734f9532018-11-15 12:13:18 -0800145 double setpoint = 10.0;
146 ec::pidinfo initial;
147
148 std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
149 &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
150 EXPECT_FALSE(p == nullptr);
151
152 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0));
153 EXPECT_CALL(z, getCachedValue(StrEq("fleeting1"))).WillOnce(Return(10.0));
154
155 EXPECT_EQ(5.0, p->inputProc());
James Feist572c43d2019-01-31 15:52:22 -0800156}
157
Josh Lehan23e22b92022-11-12 22:37:58 -0800158TEST(ThermalControllerTest, InputProc_MultipleInputsSummation)
159{
160 // This test verifies inputProc behaves as expected with multiple summation
161 // inputs.
162
163 ZoneMock z;
164
Josh Lehan31058fd2023-01-13 11:06:16 -0800165 std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"},
166 {"fleeting1"}};
Josh Lehan23e22b92022-11-12 22:37:58 -0800167 double setpoint = 10.0;
168 ec::pidinfo initial;
169
170 std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
171 &z, "therm1", inputs, setpoint, initial, ThermalType::summation);
172 EXPECT_FALSE(p == nullptr);
173
174 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0));
175 EXPECT_CALL(z, getCachedValue(StrEq("fleeting1"))).WillOnce(Return(10.0));
176
177 EXPECT_EQ(15.0, p->inputProc());
178}
179
Josh Lehan31058fd2023-01-13 11:06:16 -0800180TEST(ThermalControllerTest, InputProc_MultipleInputsTempToMargin)
181{
182 // This test verifies inputProc behaves as expected with multiple margin
183 // inputs and TempToMargin in use.
184
185 ZoneMock z;
186
187 std::vector<pid_control::conf::SensorInput> inputs = {
188 {"absolute0", 85.0, true}, {"margin1"}};
189 double setpoint = 10.0;
190 ec::pidinfo initial;
191
192 std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
193 &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
194 EXPECT_FALSE(p == nullptr);
195
196 EXPECT_CALL(z, getCachedValue(StrEq("absolute0"))).WillOnce(Return(82.0));
197 EXPECT_CALL(z, getCachedValue(StrEq("margin1"))).WillOnce(Return(5.0));
198
199 // 82 degrees temp, 85 degrees Tjmax => 3 degrees of safety margin
200 EXPECT_EQ(3.0, p->inputProc());
201}
202
James Feist572c43d2019-01-31 15:52:22 -0800203TEST(ThermalControllerTest, NegHysteresis_BehavesAsExpected)
204{
James Feist572c43d2019-01-31 15:52:22 -0800205 // This test verifies Negative hysteresis behaves as expected by
206 // crossing the setpoint and noticing readings don't change until past the
207 // hysteresis value
208
209 ZoneMock z;
210
Josh Lehan31058fd2023-01-13 11:06:16 -0800211 std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
James Feist572c43d2019-01-31 15:52:22 -0800212 double setpoint = 10.0;
213 ec::pidinfo initial;
214 initial.negativeHysteresis = 4.0;
215
216 std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
217 &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
218 EXPECT_FALSE(p == nullptr);
219
220 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0")))
221 .Times(3)
222 .WillOnce(Return(12.0))
223 .WillOnce(Return(9.0))
224 .WillOnce(Return(7.0));
225
Nirav Shahccc8bb62022-02-17 21:06:51 -0800226 EXPECT_CALL(z, addSetPoint(_, "therm1")).Times(3);
James Feist572c43d2019-01-31 15:52:22 -0800227
228 std::vector<double> lastReadings = {12.0, 12.0, 7.0};
229 for (auto& reading : lastReadings)
230 {
231 p->process();
232 EXPECT_EQ(p->getLastInput(), reading);
233 }
234}
235
236TEST(ThermalControllerTest, PosHysteresis_BehavesAsExpected)
237{
238 // This test verifies Positive hysteresis behaves as expected by
239 // crossing the setpoint and noticing readings don't change until past the
240 // hysteresis value
241
242 ZoneMock z;
243
Josh Lehan31058fd2023-01-13 11:06:16 -0800244 std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
James Feist572c43d2019-01-31 15:52:22 -0800245 double setpoint = 10.0;
246 ec::pidinfo initial;
247 initial.positiveHysteresis = 5.0;
248
249 std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
250 &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
251 EXPECT_FALSE(p == nullptr);
252
253 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0")))
254 .Times(3)
255 .WillOnce(Return(8.0))
256 .WillOnce(Return(13.0))
257 .WillOnce(Return(14.0));
258
Nirav Shahccc8bb62022-02-17 21:06:51 -0800259 EXPECT_CALL(z, addSetPoint(_, "therm1")).Times(3);
James Feist572c43d2019-01-31 15:52:22 -0800260
261 std::vector<double> lastReadings = {8.0, 8.0, 14.0};
262 for (auto& reading : lastReadings)
263 {
264 p->process();
265 EXPECT_EQ(p->getLastInput(), reading);
266 }
Patrick Venturea0764872020-08-08 07:48:43 -0700267}
268
269} // namespace
270} // namespace pid_control