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 
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 
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 
76 TEST(ZoneFromJson, oneZoneOnePidWithHysteresis)
77 {
78     // Parse a valid configuration with one zone and one PID and the PID uses
79     // Hysteresis parameters.
80 
81     std::map<int64_t, conf::PIDConf> pidConfig;
82     std::map<int64_t, conf::ZoneConfig> zoneConfig;
83 
84     auto j2 = R"(
85       {
86         "zones" : [{
87           "id": 1,
88           "minThermalOutput": 3000.0,
89           "failsafePercent": 75.0,
90           "pids": [{
91             "name": "fan1-5",
92             "type": "fan",
93             "inputs": ["fan1", "fan5"],
94             "setpoint": 90.0,
95             "pid": {
96               "samplePeriod": 0.1,
97               "proportionalCoeff": 0.0,
98               "integralCoeff": 0.0,
99               "derivativeCoeff": 0.0,
100               "feedFwdOffsetCoeff": 0.0,
101               "feedFwdGainCoeff": 0.010,
102               "integralLimit_min": 0.0,
103               "integralLimit_max": 0.0,
104               "outLim_min": 30.0,
105               "outLim_max": 100.0,
106               "slewNeg": 0.0,
107               "slewPos": 0.0,
108               "positiveHysteresis": 1000.0,
109               "negativeHysteresis": 9000.0
110             }
111           }]
112         }]
113       }
114     )"_json;
115 
116     std::tie(pidConfig, zoneConfig) = buildPIDsFromJson(j2);
117     EXPECT_EQ(pidConfig.size(), static_cast<u_int64_t>(1));
118     EXPECT_EQ(zoneConfig.size(), static_cast<u_int64_t>(1));
119 
120     EXPECT_EQ(pidConfig[1]["fan1-5"].type, "fan");
121     EXPECT_DOUBLE_EQ(pidConfig[1]["fan1-5"].pidInfo.positiveHysteresis, 1000.0);
122 
123     EXPECT_DOUBLE_EQ(zoneConfig[1].minThermalOutput, 3000.0);
124 }
125 
126 TEST(ZoneFromJson, oneZoneOneStepwiseWithHysteresis)
127 {
128     // Parse a valid configuration with one zone and one PID and the PID uses
129     // Hysteresis parameters.
130 
131     std::map<int64_t, conf::PIDConf> pidConfig;
132     std::map<int64_t, conf::ZoneConfig> zoneConfig;
133 
134     auto j2 = R"(
135       {
136         "zones" : [{
137           "id": 1,
138           "minThermalOutput": 3000.0,
139           "failsafePercent": 75.0,
140           "pids": [{
141             "name": "temp1",
142             "type": "stepwise",
143             "inputs": ["temp1"],
144             "setpoint": 30.0,
145             "pid": {
146               "samplePeriod": 0.1,
147               "positiveHysteresis": 1.0,
148               "negativeHysteresis": 1.0,
149               "isCeiling": false,
150               "reading": {
151                 "0": 45,
152                 "1": 46,
153                 "2": 47,
154                 "3": 48,
155                 "4": 49,
156                 "5": 50,
157                 "6": 51,
158                 "7": 52,
159                 "8": 53,
160                 "9": 54,
161                 "10": 55,
162                 "11": 56,
163                 "12": 57,
164                 "13": 58,
165                 "14": 59,
166                 "15": 60,
167                 "16": 61,
168                 "17": 62,
169                 "18": 63,
170                 "19": 64
171               },
172               "output": {
173                 "0": 5000,
174                 "1": 2400,
175                 "2": 2600,
176                 "3": 2800,
177                 "4": 3000,
178                 "5": 3200,
179                 "6": 3400,
180                 "7": 3600,
181                 "8": 3800,
182                 "9": 4000,
183                 "10": 4200,
184                 "11": 4400,
185                 "12": 4600,
186                 "13": 4800,
187                 "14": 5000,
188                 "15": 5200,
189                 "16": 5400,
190                 "17": 5600,
191                 "18": 5800,
192                 "19": 6000
193               }
194             }
195           }]
196         }]
197       }
198     )"_json;
199 
200     std::tie(pidConfig, zoneConfig) = buildPIDsFromJson(j2);
201     EXPECT_EQ(pidConfig.size(), static_cast<u_int64_t>(1));
202     EXPECT_EQ(zoneConfig.size(), static_cast<u_int64_t>(1));
203 
204     EXPECT_EQ(pidConfig[1]["temp1"].type, "stepwise");
205     EXPECT_DOUBLE_EQ(pidConfig[1]["temp1"].stepwiseInfo.positiveHysteresis,
206                      1.0);
207 
208     EXPECT_DOUBLE_EQ(zoneConfig[1].minThermalOutput, 3000.0);
209 }
210 
211 TEST(ZoneFromJson, getCycleInterval)
212 {
213     // Parse a valid configuration with one zone and one PID and the zone have
214     // cycleIntervalTime and updateThermalsTime parameters.
215 
216     std::map<int64_t, conf::PIDConf> pidConfig;
217     std::map<int64_t, conf::ZoneConfig> zoneConfig;
218 
219     auto j2 = R"(
220       {
221         "zones" : [{
222           "id": 1,
223           "minThermalOutput": 3000.0,
224           "failsafePercent": 75.0,
225           "cycleIntervalTimeMS": 1000.0,
226           "updateThermalsTimeMS": 1000.0,
227           "pids": [{
228             "name": "fan1-5",
229             "type": "fan",
230             "inputs": ["fan1", "fan5"],
231             "setpoint": 90.0,
232             "pid": {
233               "samplePeriod": 0.1,
234               "proportionalCoeff": 0.0,
235               "integralCoeff": 0.0,
236               "derivativeCoeff": 0.0,
237               "feedFwdOffsetCoeff": 0.0,
238               "feedFwdGainCoeff": 0.010,
239               "integralLimit_min": 0.0,
240               "integralLimit_max": 0.0,
241               "outLim_min": 30.0,
242               "outLim_max": 100.0,
243               "slewNeg": 0.0,
244               "slewPos": 0.0
245             }
246           }]
247         }]
248       }
249     )"_json;
250 
251     std::tie(pidConfig, zoneConfig) = buildPIDsFromJson(j2);
252     EXPECT_EQ(pidConfig.size(), 1);
253     EXPECT_EQ(zoneConfig.size(), 1);
254 
255     EXPECT_EQ(pidConfig[1]["fan1-5"].type, "fan");
256     EXPECT_EQ(zoneConfig[1].cycleTime.cycleIntervalTimeMS, 1000);
257     // updateThermalsTimeMS would be updated as updateThermalsTimeMS /
258     // cycleIntervalTimeMS
259     EXPECT_EQ(zoneConfig[1].cycleTime.updateThermalsTimeMS, 1);
260     EXPECT_DOUBLE_EQ(zoneConfig[1].minThermalOutput, 3000.0);
261 }
262 
263 } // namespace
264 } // namespace pid_control
265