test dc_motor.cpp (#2890)

* use ipwm where possible

* mock ipwm

* initialize

* test
This commit is contained in:
Matthew Kennedy 2021-07-01 06:21:18 -07:00 committed by GitHub
parent 35ad1b7d89
commit 1bca4843fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 141 additions and 13 deletions

View File

@ -31,7 +31,7 @@ static boostOpenLoop_Map3D_t boostMapOpen;
static boostOpenLoop_Map3D_t boostMapClosed; static boostOpenLoop_Map3D_t boostMapClosed;
static SimplePwm boostPwmControl("boost"); static SimplePwm boostPwmControl("boost");
void BoostController::init(SimplePwm* pwm, const ValueProvider3D* openLoopMap, const ValueProvider3D* closedLoopTargetMap, pid_s* pidParams) { void BoostController::init(IPwm* pwm, const ValueProvider3D* openLoopMap, const ValueProvider3D* closedLoopTargetMap, pid_s* pidParams) {
m_pwm = pwm; m_pwm = pwm;
m_openLoopMap = openLoopMap; m_openLoopMap = openLoopMap;
m_closedLoopTargetMap = closedLoopTargetMap; m_closedLoopTargetMap = closedLoopTargetMap;

View File

@ -11,13 +11,13 @@
#include "closed_loop_controller.h" #include "closed_loop_controller.h"
#include "pid.h" #include "pid.h"
class SimplePwm; class IPwm;
class BoostController : public ClosedLoopController<float, percent_t> { class BoostController : public ClosedLoopController<float, percent_t> {
public: public:
DECLARE_ENGINE_PTR; DECLARE_ENGINE_PTR;
void init(SimplePwm* pmw, const ValueProvider3D* openLoopMap, const ValueProvider3D* closedLoopTargetMap, pid_s* pidParams); void init(IPwm* pmw, const ValueProvider3D* openLoopMap, const ValueProvider3D* closedLoopTargetMap, pid_s* pidParams);
void update(); void update();
// Called when the configuration may have changed. Controller will // Called when the configuration may have changed. Controller will
@ -39,7 +39,7 @@ private:
const ValueProvider3D* m_openLoopMap = nullptr; const ValueProvider3D* m_openLoopMap = nullptr;
const ValueProvider3D* m_closedLoopTargetMap = nullptr; const ValueProvider3D* m_closedLoopTargetMap = nullptr;
SimplePwm* m_pwm = nullptr; IPwm* m_pwm = nullptr;
}; };
void startBoostPin(); void startBoostPin();

View File

@ -59,7 +59,7 @@ void GppwmChannel::setOutput(float result) {
} }
} }
void GppwmChannel::init(bool usePwm, SimplePwm* pwm, OutputPin* outputPin, const ValueProvider3D* table, const gppwm_channel* config) { void GppwmChannel::init(bool usePwm, IPwm* pwm, OutputPin* outputPin, const ValueProvider3D* table, const gppwm_channel* config) {
m_usePwm = usePwm; m_usePwm = usePwm;
m_pwm = pwm; m_pwm = pwm;
m_output = outputPin; m_output = outputPin;

View File

@ -6,14 +6,14 @@
struct gppwm_channel; struct gppwm_channel;
class OutputPin; class OutputPin;
class SimplePwm; class IPwm;
class ValueProvider3D; class ValueProvider3D;
class GppwmChannel { class GppwmChannel {
public: public:
DECLARE_ENGINE_PTR; DECLARE_ENGINE_PTR;
void init(bool usePwm, SimplePwm* pwm, OutputPin* outputPin, const ValueProvider3D* table, const gppwm_channel* config); void init(bool usePwm, IPwm* pwm, OutputPin* outputPin, const ValueProvider3D* table, const gppwm_channel* config);
float update(); float update();
percent_t getOutput() const; percent_t getOutput() const;
void setOutput(float result); void setOutput(float result);
@ -25,7 +25,7 @@ private:
// Configuration fields // Configuration fields
const gppwm_channel* m_config = nullptr; const gppwm_channel* m_config = nullptr;
bool m_usePwm = false; bool m_usePwm = false;
SimplePwm* m_pwm = nullptr; IPwm* m_pwm = nullptr;
OutputPin* m_output = nullptr; OutputPin* m_output = nullptr;
const ValueProvider3D* m_table = nullptr; const ValueProvider3D* m_table = nullptr;
}; };

View File

@ -71,9 +71,9 @@ public:
}; };
private: private:
IPwm* m_enable; IPwm* m_enable = nullptr;
IPwm* m_dir1; IPwm* m_dir1 = nullptr;
IPwm* m_dir2; IPwm* m_dir2 = nullptr;
OutputPin* const m_disable; OutputPin* const m_disable;
float m_value = 0; float m_value = 0;

View File

@ -42,7 +42,7 @@ public:
MOCK_METHOD(float, getValue, (float xColumn, float yRow), (const, override)); MOCK_METHOD(float, getValue, (float xColumn, float yRow), (const, override));
}; };
class MockPwm : public SimplePwm { class MockPwm : public IPwm {
public: public:
MOCK_METHOD(void, setSimplePwmDutyCycle, (float dutyCycle), (override)); MOCK_METHOD(void, setSimplePwmDutyCycle, (float dutyCycle), (override));
}; };

View File

@ -0,0 +1,126 @@
#include "dc_motor.h"
#include "mocks.h"
using ::testing::InSequence;
using ::testing::NiceMock;
using ::testing::StrictMock;
TEST(DcMotor, Disable) {
StrictMock<MockOutputPin> dpin;
EXPECT_CALL(dpin, setValue(1))
.Times(2); // happens twice - once for initial disable, once for set(0)
TwoPinDcMotor dut(dpin);
}
TEST(DcMotor, Disable2) {
StrictMock<MockOutputPin> dpin;
EXPECT_CALL(dpin, setValue(1)).Times(4);
TwoPinDcMotor dut(dpin);
dut.disable();
}
TEST(DcMotor, Enable) {
StrictMock<MockOutputPin> dpin;
{
InSequence is;
// Construction disables
EXPECT_CALL(dpin, setValue(1)).Times(2);
// Then enable
EXPECT_CALL(dpin, setValue(0));
}
TwoPinDcMotor dut(dpin);
dut.enable();
}
TEST(DcMotor, SetUnconfigured) {
StrictMock<MockOutputPin> dpin;
EXPECT_CALL(dpin, setValue(1)).Times(3);
TwoPinDcMotor dut(dpin);
EXPECT_FLOAT_EQ(dut.get(), 0);
EXPECT_NO_THROW(dut.set(0.5f));
// Readback should work even without configuration
EXPECT_FLOAT_EQ(dut.get(), 0.5f);
}
TEST(DcMotor, PwmEnablePinModePositive) {
NiceMock<MockOutputPin> dpin;
TwoPinDcMotor dut(dpin);
dut.setType(TwoPinDcMotor::ControlType::PwmEnablePin);
MockPwm enable;
MockPwm dir1;
MockPwm dir2;
EXPECT_CALL(enable, setSimplePwmDutyCycle(0.5f));
EXPECT_CALL(dir1, setSimplePwmDutyCycle(1));
EXPECT_CALL(dir2, setSimplePwmDutyCycle(0));
dut.configure(enable, dir1, dir2);
dut.set(0.5f);
}
TEST(DcMotor, PwmEnablePinModeNegative) {
NiceMock<MockOutputPin> dpin;
TwoPinDcMotor dut(dpin);
dut.setType(TwoPinDcMotor::ControlType::PwmEnablePin);
MockPwm enable;
MockPwm dir1;
MockPwm dir2;
EXPECT_CALL(enable, setSimplePwmDutyCycle(0.5f));
EXPECT_CALL(dir1, setSimplePwmDutyCycle(0));
EXPECT_CALL(dir2, setSimplePwmDutyCycle(1));
dut.configure(enable, dir1, dir2);
dut.set(-0.5f);
}
TEST(DcMotor, PwmDirectionPinsModePositive) {
NiceMock<MockOutputPin> dpin;
TwoPinDcMotor dut(dpin);
dut.setType(TwoPinDcMotor::ControlType::PwmDirectionPins);
MockPwm enable;
MockPwm dir1;
MockPwm dir2;
EXPECT_CALL(enable, setSimplePwmDutyCycle(1));
EXPECT_CALL(dir1, setSimplePwmDutyCycle(0.5f));
EXPECT_CALL(dir2, setSimplePwmDutyCycle(0));
dut.configure(enable, dir1, dir2);
dut.set(0.5f);
}
TEST(DcMotor, PwmDirectionPinsModeNegative) {
NiceMock<MockOutputPin> dpin;
TwoPinDcMotor dut(dpin);
dut.setType(TwoPinDcMotor::ControlType::PwmDirectionPins);
MockPwm enable;
MockPwm dir1;
MockPwm dir2;
EXPECT_CALL(enable, setSimplePwmDutyCycle(1));
EXPECT_CALL(dir1, setSimplePwmDutyCycle(0));
EXPECT_CALL(dir2, setSimplePwmDutyCycle(0.5f));
dut.configure(enable, dir1, dir2);
dut.set(-0.5f);
}

View File

@ -7,13 +7,14 @@
#include "mocks.h" #include "mocks.h"
using ::testing::InSequence; using ::testing::InSequence;
using ::testing::StrictMock;
TEST(GpPwm, OutputWithPwm) { TEST(GpPwm, OutputWithPwm) {
GppwmChannel ch; GppwmChannel ch;
gppwm_channel cfg; gppwm_channel cfg;
MockPwm pwm; StrictMock<MockPwm> pwm;
// Shouldn't throw with no config // Shouldn't throw with no config
EXPECT_NO_THROW(ch.setOutput(10)); EXPECT_NO_THROW(ch.setOutput(10));

View File

@ -38,6 +38,7 @@ TESTS_SRC_CPP = \
tests/test_idle_controller.cpp \ tests/test_idle_controller.cpp \
tests/test_issue_898.cpp \ tests/test_issue_898.cpp \
tests/test_etb.cpp \ tests/test_etb.cpp \
tests/test_dc_motor.cpp \
tests/test_fan_control.cpp \ tests/test_fan_control.cpp \
tests/test_vvt.cpp \ tests/test_vvt.cpp \
tests/test_launch.cpp \ tests/test_launch.cpp \