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, 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 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 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 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