1 #include "pid/buildjson.hpp"
2
3 #include <gmock/gmock.h>
4 #include <gtest/gtest.h>
5
6 namespace pid_control
7 {
8 namespace
9 {
10
TEST(ZoneFromJson,emptyZone)11 TEST(ZoneFromJson, emptyZone)
12 {
13 // There is a zone key, but it's empty.
14 // This is technically invalid.
15
16 std::map<int64_t, conf::PIDConf> pidConfig;
17 std::map<int64_t, conf::ZoneConfig> zoneConfig;
18
19 auto j2 = R"(
20 {
21 "zones": []
22 }
23 )"_json;
24
25 std::tie(pidConfig, zoneConfig) = buildPIDsFromJson(j2);
26
27 EXPECT_TRUE(pidConfig.empty());
28 EXPECT_TRUE(zoneConfig.empty());
29 }
30
TEST(ZoneFromJson,oneZoneOnePid)31 TEST(ZoneFromJson, oneZoneOnePid)
32 {
33 // Parse a valid configuration with one zone and one PID.
34 // Intentionally omits "derivativeCoeff" to test that it is optional.
35
36 std::map<int64_t, conf::PIDConf> pidConfig;
37 std::map<int64_t, conf::ZoneConfig> zoneConfig;
38
39 auto j2 = R"(
40 {
41 "zones" : [{
42 "id": 1,
43 "minThermalOutput": 3000.0,
44 "failsafePercent": 75.0,
45 "pids": [{
46 "name": "fan1-5",
47 "type": "fan",
48 "inputs": ["fan1", "fan5"],
49 "setpoint": 90.0,
50 "pid": {
51 "samplePeriod": 0.1,
52 "proportionalCoeff": 0.0,
53 "integralCoeff": 0.0,
54 "feedFwdOffsetCoeff": 0.0,
55 "feedFwdGainCoeff": 0.010,
56 "integralLimit_min": 0.0,
57 "integralLimit_max": 0.0,
58 "outLim_min": 30.0,
59 "outLim_max": 100.0,
60 "slewNeg": 0.0,
61 "slewPos": 0.0
62 }
63 }]
64 }]
65 }
66 )"_json;
67
68 std::tie(pidConfig, zoneConfig) = buildPIDsFromJson(j2);
69 EXPECT_EQ(pidConfig.size(), static_cast<u_int64_t>(1));
70 EXPECT_EQ(zoneConfig.size(), static_cast<u_int64_t>(1));
71
72 EXPECT_EQ(pidConfig[1]["fan1-5"].type, "fan");
73 EXPECT_DOUBLE_EQ(zoneConfig[1].minThermalOutput, 3000.0);
74 }
75
TEST(ZoneFromJson,marginZone)76 TEST(ZoneFromJson, marginZone)
77 {
78 // Parse a valid configuration with one zone and one PID.
79 // This is a margin zone, and has both kinds of temperature
80 // sensors in it, absolute temperature and margin temperature.
81 // Tests that TempToMargin is parsed correctly.
82
83 std::map<int64_t, conf::PIDConf> pidConfig;
84 std::map<int64_t, conf::ZoneConfig> zoneConfig;
85
86 auto j2 = R"(
87 {
88 "zones" : [{
89 "id": 1,
90 "minThermalOutput": 3000.0,
91 "failsafePercent": 75.0,
92 "pids": [{
93 "name": "myPid",
94 "type": "margin",
95 "inputs": ["absolute0", "absolute1", "margin0", "margin1"],
96 "tempToMargin": [
97 85.0,
98 100.0
99 ],
100 "setpoint": 10.0,
101 "pid": {
102 "samplePeriod": 0.1,
103 "proportionalCoeff": 0.0,
104 "integralCoeff": 0.0,
105 "feedFwdOffsetCoeff": 0.0,
106 "feedFwdGainCoeff": 0.010,
107 "integralLimit_min": 0.0,
108 "integralLimit_max": 0.0,
109 "outLim_min": 30.0,
110 "outLim_max": 100.0,
111 "slewNeg": 0.0,
112 "slewPos": 0.0
113 }
114 }]
115 }]
116 }
117 )"_json;
118
119 std::tie(pidConfig, zoneConfig) = buildPIDsFromJson(j2);
120 EXPECT_EQ(pidConfig.size(), static_cast<u_int64_t>(1));
121 EXPECT_EQ(zoneConfig.size(), static_cast<u_int64_t>(1));
122
123 EXPECT_EQ(pidConfig[1]["myPid"].type, "margin");
124 EXPECT_DOUBLE_EQ(zoneConfig[1].minThermalOutput, 3000.0);
125
126 EXPECT_EQ(pidConfig[1]["myPid"].inputs[0].name, "absolute0");
127 EXPECT_DOUBLE_EQ(pidConfig[1]["myPid"].inputs[0].convertMarginZero, 85.0);
128 EXPECT_EQ(pidConfig[1]["myPid"].inputs[0].convertTempToMargin, true);
129
130 EXPECT_EQ(pidConfig[1]["myPid"].inputs[1].name, "absolute1");
131 EXPECT_DOUBLE_EQ(pidConfig[1]["myPid"].inputs[1].convertMarginZero, 100.0);
132 EXPECT_EQ(pidConfig[1]["myPid"].inputs[1].convertTempToMargin, true);
133
134 EXPECT_EQ(pidConfig[1]["myPid"].inputs[2].name, "margin0");
135 EXPECT_EQ(pidConfig[1]["myPid"].inputs[2].convertTempToMargin, false);
136
137 EXPECT_EQ(pidConfig[1]["myPid"].inputs[3].name, "margin1");
138 EXPECT_EQ(pidConfig[1]["myPid"].inputs[3].convertTempToMargin, false);
139 }
140
TEST(ZoneFromJson,oneZoneOnePidWithHysteresis)141 TEST(ZoneFromJson, oneZoneOnePidWithHysteresis)
142 {
143 // Parse a valid configuration with one zone and one PID and the PID uses
144 // Hysteresis parameters.
145
146 std::map<int64_t, conf::PIDConf> pidConfig;
147 std::map<int64_t, conf::ZoneConfig> zoneConfig;
148
149 auto j2 = R"(
150 {
151 "zones" : [{
152 "id": 1,
153 "minThermalOutput": 3000.0,
154 "failsafePercent": 75.0,
155 "pids": [{
156 "name": "fan1-5",
157 "type": "fan",
158 "inputs": ["fan1", "fan5"],
159 "setpoint": 90.0,
160 "pid": {
161 "samplePeriod": 0.1,
162 "proportionalCoeff": 0.0,
163 "integralCoeff": 0.0,
164 "derivativeCoeff": 0.0,
165 "feedFwdOffsetCoeff": 0.0,
166 "feedFwdGainCoeff": 0.010,
167 "integralLimit_min": 0.0,
168 "integralLimit_max": 0.0,
169 "outLim_min": 30.0,
170 "outLim_max": 100.0,
171 "slewNeg": 0.0,
172 "slewPos": 0.0,
173 "positiveHysteresis": 1000.0,
174 "negativeHysteresis": 9000.0
175 }
176 }]
177 }]
178 }
179 )"_json;
180
181 std::tie(pidConfig, zoneConfig) = buildPIDsFromJson(j2);
182 EXPECT_EQ(pidConfig.size(), static_cast<u_int64_t>(1));
183 EXPECT_EQ(zoneConfig.size(), static_cast<u_int64_t>(1));
184
185 EXPECT_EQ(pidConfig[1]["fan1-5"].type, "fan");
186 EXPECT_DOUBLE_EQ(pidConfig[1]["fan1-5"].pidInfo.positiveHysteresis, 1000.0);
187
188 EXPECT_DOUBLE_EQ(zoneConfig[1].minThermalOutput, 3000.0);
189 }
190
TEST(ZoneFromJson,oneZoneOneStepwiseWithHysteresis)191 TEST(ZoneFromJson, oneZoneOneStepwiseWithHysteresis)
192 {
193 // Parse a valid configuration with one zone and one PID and the PID uses
194 // Hysteresis parameters.
195
196 std::map<int64_t, conf::PIDConf> pidConfig;
197 std::map<int64_t, conf::ZoneConfig> zoneConfig;
198
199 auto j2 = R"(
200 {
201 "zones" : [{
202 "id": 1,
203 "minThermalOutput": 3000.0,
204 "failsafePercent": 75.0,
205 "pids": [{
206 "name": "temp1",
207 "type": "stepwise",
208 "inputs": ["temp1"],
209 "setpoint": 30.0,
210 "pid": {
211 "samplePeriod": 0.1,
212 "positiveHysteresis": 1.0,
213 "negativeHysteresis": 1.0,
214 "isCeiling": false,
215 "reading": {
216 "0": 45,
217 "1": 46,
218 "2": 47,
219 "3": 48,
220 "4": 49,
221 "5": 50,
222 "6": 51,
223 "7": 52,
224 "8": 53,
225 "9": 54,
226 "10": 55,
227 "11": 56,
228 "12": 57,
229 "13": 58,
230 "14": 59,
231 "15": 60,
232 "16": 61,
233 "17": 62,
234 "18": 63,
235 "19": 64
236 },
237 "output": {
238 "0": 5000,
239 "1": 2400,
240 "2": 2600,
241 "3": 2800,
242 "4": 3000,
243 "5": 3200,
244 "6": 3400,
245 "7": 3600,
246 "8": 3800,
247 "9": 4000,
248 "10": 4200,
249 "11": 4400,
250 "12": 4600,
251 "13": 4800,
252 "14": 5000,
253 "15": 5200,
254 "16": 5400,
255 "17": 5600,
256 "18": 5800,
257 "19": 6000
258 }
259 }
260 }]
261 }]
262 }
263 )"_json;
264
265 std::tie(pidConfig, zoneConfig) = buildPIDsFromJson(j2);
266 EXPECT_EQ(pidConfig.size(), static_cast<u_int64_t>(1));
267 EXPECT_EQ(zoneConfig.size(), static_cast<u_int64_t>(1));
268
269 EXPECT_EQ(pidConfig[1]["temp1"].type, "stepwise");
270 EXPECT_DOUBLE_EQ(pidConfig[1]["temp1"].stepwiseInfo.positiveHysteresis,
271 1.0);
272
273 EXPECT_DOUBLE_EQ(zoneConfig[1].minThermalOutput, 3000.0);
274 }
275
TEST(ZoneFromJson,getCycleInterval)276 TEST(ZoneFromJson, getCycleInterval)
277 {
278 // Parse a valid configuration with one zone and one PID and the zone have
279 // cycleIntervalTime and updateThermalsTime parameters.
280
281 std::map<int64_t, conf::PIDConf> pidConfig;
282 std::map<int64_t, conf::ZoneConfig> zoneConfig;
283
284 auto j2 = R"(
285 {
286 "zones" : [{
287 "id": 1,
288 "minThermalOutput": 3000.0,
289 "failsafePercent": 75.0,
290 "cycleIntervalTimeMS": 1000.0,
291 "updateThermalsTimeMS": 1000.0,
292 "pids": [{
293 "name": "fan1-5",
294 "type": "fan",
295 "inputs": ["fan1", "fan5"],
296 "setpoint": 90.0,
297 "pid": {
298 "samplePeriod": 0.1,
299 "proportionalCoeff": 0.0,
300 "integralCoeff": 0.0,
301 "derivativeCoeff": 0.0,
302 "feedFwdOffsetCoeff": 0.0,
303 "feedFwdGainCoeff": 0.010,
304 "integralLimit_min": 0.0,
305 "integralLimit_max": 0.0,
306 "outLim_min": 30.0,
307 "outLim_max": 100.0,
308 "slewNeg": 0.0,
309 "slewPos": 0.0
310 }
311 }]
312 }]
313 }
314 )"_json;
315
316 std::tie(pidConfig, zoneConfig) = buildPIDsFromJson(j2);
317 EXPECT_EQ(pidConfig.size(), static_cast<u_int64_t>(1));
318 EXPECT_EQ(zoneConfig.size(), static_cast<u_int64_t>(1));
319
320 EXPECT_EQ(pidConfig[1]["fan1-5"].type, "fan");
321 EXPECT_EQ(zoneConfig[1].cycleTime.cycleIntervalTimeMS,
322 static_cast<u_int64_t>(1000));
323 EXPECT_EQ(zoneConfig[1].cycleTime.updateThermalsTimeMS,
324 static_cast<u_int64_t>(1000));
325 EXPECT_DOUBLE_EQ(zoneConfig[1].minThermalOutput, 3000.0);
326 }
327
328 } // namespace
329 } // namespace pid_control
330