1 #include "pid/ec/pid.hpp" 2 #include "pid/thermalcontroller.hpp" 3 #include "test/zone_mock.hpp" 4 5 #include <string> 6 #include <vector> 7 8 #include <gmock/gmock.h> 9 #include <gtest/gtest.h> 10 11 using ::testing::_; 12 using ::testing::Return; 13 using ::testing::StrEq; 14 15 TEST(ThermalControllerTest, BoringFactoryTest) 16 { 17 // Verifies building a ThermalPIDController with the factory works as 18 // expected in the boring (uninteresting) case. 19 20 ZoneMock z; 21 22 std::vector<std::string> inputs = {"fleeting0"}; 23 double setpoint = 10.0; 24 ec::pidinfo initial; 25 26 std::unique_ptr<PIDController> p = ThermalController::createThermalPid( 27 &z, "therm1", inputs, setpoint, initial, ThermalType::margin); 28 // Success 29 EXPECT_FALSE(p == nullptr); 30 } 31 32 TEST(ThermalControllerTest, VerifyFactoryFailsWithZeroInputs) 33 { 34 // A thermal controller needs at least one input. 35 36 ZoneMock z; 37 38 std::vector<std::string> inputs = {}; 39 double setpoint = 10.0; 40 ec::pidinfo initial; 41 std::unique_ptr<PIDController> p; 42 EXPECT_THROW( 43 { 44 p = ThermalController::createThermalPid( 45 &z, "therm1", inputs, setpoint, initial, ThermalType::margin); 46 }, 47 std::exception); 48 EXPECT_TRUE(p == nullptr); 49 } 50 51 TEST(ThermalControllerTest, InputProc_BehavesAsExpected) 52 { 53 // This test just verifies inputProc behaves as expected. 54 55 ZoneMock z; 56 57 std::vector<std::string> inputs = {"fleeting0"}; 58 double setpoint = 10.0; 59 ec::pidinfo initial; 60 61 std::unique_ptr<PIDController> p = ThermalController::createThermalPid( 62 &z, "therm1", inputs, setpoint, initial, ThermalType::margin); 63 EXPECT_FALSE(p == nullptr); 64 65 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0)); 66 67 EXPECT_EQ(5.0, p->inputProc()); 68 } 69 70 TEST(ThermalControllerTest, SetPtProc_BehavesAsExpected) 71 { 72 // This test just verifies inputProc behaves as expected. 73 74 ZoneMock z; 75 76 std::vector<std::string> inputs = {"fleeting0"}; 77 double setpoint = 10.0; 78 ec::pidinfo initial; 79 80 std::unique_ptr<PIDController> p = ThermalController::createThermalPid( 81 &z, "therm1", inputs, setpoint, initial, ThermalType::margin); 82 EXPECT_FALSE(p == nullptr); 83 84 EXPECT_EQ(setpoint, p->setptProc()); 85 } 86 87 TEST(ThermalControllerTest, OutputProc_BehavesAsExpected) 88 { 89 // This test just verifies outputProc behaves as expected. 90 91 ZoneMock z; 92 93 std::vector<std::string> inputs = {"fleeting0"}; 94 double setpoint = 10.0; 95 ec::pidinfo initial; 96 97 std::unique_ptr<PIDController> p = ThermalController::createThermalPid( 98 &z, "therm1", inputs, setpoint, initial, ThermalType::margin); 99 EXPECT_FALSE(p == nullptr); 100 101 double value = 90.0; 102 EXPECT_CALL(z, addRPMSetPoint(value)); 103 104 p->outputProc(value); 105 } 106 107 TEST(ThermalControllerTest, InputProc_MultipleInputsAbsolute) 108 { 109 // This test verifies inputProc behaves as expected with multiple absolute 110 // inputs. 111 112 ZoneMock z; 113 114 std::vector<std::string> inputs = {"fleeting0", "fleeting1"}; 115 double setpoint = 10.0; 116 ec::pidinfo initial; 117 118 std::unique_ptr<PIDController> p = ThermalController::createThermalPid( 119 &z, "therm1", inputs, setpoint, initial, ThermalType::absolute); 120 EXPECT_FALSE(p == nullptr); 121 122 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0)); 123 EXPECT_CALL(z, getCachedValue(StrEq("fleeting1"))).WillOnce(Return(10.0)); 124 125 EXPECT_EQ(10.0, p->inputProc()); 126 } 127 128 TEST(ThermalControllerTest, InputProc_MultipleInputsMargin) 129 { 130 // This test verifies inputProc behaves as expected with multiple margin 131 // inputs. 132 133 ZoneMock z; 134 135 std::vector<std::string> inputs = {"fleeting0", "fleeting1"}; 136 double setpoint = 10.0; 137 ec::pidinfo initial; 138 139 std::unique_ptr<PIDController> p = ThermalController::createThermalPid( 140 &z, "therm1", inputs, setpoint, initial, ThermalType::margin); 141 EXPECT_FALSE(p == nullptr); 142 143 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0)); 144 EXPECT_CALL(z, getCachedValue(StrEq("fleeting1"))).WillOnce(Return(10.0)); 145 146 EXPECT_EQ(5.0, p->inputProc()); 147 } 148 149 TEST(ThermalControllerTest, NegHysteresis_BehavesAsExpected) 150 { 151 152 // This test verifies Negative hysteresis behaves as expected by 153 // crossing the setpoint and noticing readings don't change until past the 154 // hysteresis value 155 156 ZoneMock z; 157 158 std::vector<std::string> inputs = {"fleeting0"}; 159 double setpoint = 10.0; 160 ec::pidinfo initial; 161 initial.negativeHysteresis = 4.0; 162 163 std::unique_ptr<PIDController> p = ThermalController::createThermalPid( 164 &z, "therm1", inputs, setpoint, initial, ThermalType::margin); 165 EXPECT_FALSE(p == nullptr); 166 167 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))) 168 .Times(3) 169 .WillOnce(Return(12.0)) 170 .WillOnce(Return(9.0)) 171 .WillOnce(Return(7.0)); 172 173 EXPECT_CALL(z, addRPMSetPoint(_)).Times(3); 174 175 std::vector<double> lastReadings = {12.0, 12.0, 7.0}; 176 for (auto& reading : lastReadings) 177 { 178 p->process(); 179 EXPECT_EQ(p->getLastInput(), reading); 180 } 181 } 182 183 TEST(ThermalControllerTest, PosHysteresis_BehavesAsExpected) 184 { 185 // This test verifies Positive hysteresis behaves as expected by 186 // crossing the setpoint and noticing readings don't change until past the 187 // hysteresis value 188 189 ZoneMock z; 190 191 std::vector<std::string> inputs = {"fleeting0"}; 192 double setpoint = 10.0; 193 ec::pidinfo initial; 194 initial.positiveHysteresis = 5.0; 195 196 std::unique_ptr<PIDController> p = ThermalController::createThermalPid( 197 &z, "therm1", inputs, setpoint, initial, ThermalType::margin); 198 EXPECT_FALSE(p == nullptr); 199 200 EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))) 201 .Times(3) 202 .WillOnce(Return(8.0)) 203 .WillOnce(Return(13.0)) 204 .WillOnce(Return(14.0)); 205 206 EXPECT_CALL(z, addRPMSetPoint(_)).Times(3); 207 208 std::vector<double> lastReadings = {8.0, 8.0, 14.0}; 209 for (auto& reading : lastReadings) 210 { 211 p->process(); 212 EXPECT_EQ(p->getLastInput(), reading); 213 } 214 }