mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
[wpilibc] Clean up integration tests (#3400)
The command and shuffleboard integration tests were removed because their unit tests counterparts already provide adequate coverage. Java already removed these.
This commit is contained in:
@@ -12,41 +12,23 @@
|
||||
#include "frc/Timer.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static constexpr auto kDelayTime = 10_ms;
|
||||
|
||||
/**
|
||||
* A fixture with an analog input and an analog output wired together
|
||||
*/
|
||||
class AnalogLoopTest : public testing::Test {
|
||||
protected:
|
||||
AnalogInput* m_input;
|
||||
AnalogOutput* m_output;
|
||||
|
||||
void SetUp() override {
|
||||
m_input = new AnalogInput(TestBench::kFakeAnalogOutputChannel);
|
||||
m_output = new AnalogOutput(TestBench::kAnalogOutputChannel);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete m_input;
|
||||
delete m_output;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test analog inputs and outputs by setting one and making sure the other
|
||||
* matches.
|
||||
*/
|
||||
TEST_F(AnalogLoopTest, AnalogInputWorks) {
|
||||
TEST(AnalogLoopTest, AnalogInputWorks) {
|
||||
frc::AnalogInput input{TestBench::kFakeAnalogOutputChannel};
|
||||
frc::AnalogOutput output{TestBench::kAnalogOutputChannel};
|
||||
|
||||
// Set the output voltage and check if the input measures the same voltage
|
||||
for (int32_t i = 0; i < 50; i++) {
|
||||
m_output->SetVoltage(i / 10.0);
|
||||
output.SetVoltage(i / 10.0);
|
||||
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
EXPECT_NEAR(m_output->GetVoltage(), m_input->GetVoltage(), 0.01);
|
||||
EXPECT_NEAR(output.GetVoltage(), input.GetVoltage(), 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,26 +36,29 @@ TEST_F(AnalogLoopTest, AnalogInputWorks) {
|
||||
* Test if we can use an analog trigger to check if the output is within a
|
||||
* range correctly.
|
||||
*/
|
||||
TEST_F(AnalogLoopTest, AnalogTriggerWorks) {
|
||||
AnalogTrigger trigger(m_input);
|
||||
TEST(AnalogLoopTest, AnalogTriggerWorks) {
|
||||
frc::AnalogInput input{TestBench::kFakeAnalogOutputChannel};
|
||||
frc::AnalogOutput output{TestBench::kAnalogOutputChannel};
|
||||
|
||||
frc::AnalogTrigger trigger{&input};
|
||||
trigger.SetLimitsVoltage(2.0, 3.0);
|
||||
|
||||
m_output->SetVoltage(1.0);
|
||||
Wait(kDelayTime);
|
||||
output.SetVoltage(1.0);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
EXPECT_FALSE(trigger.GetInWindow())
|
||||
<< "Analog trigger is in the window (2V, 3V)";
|
||||
EXPECT_FALSE(trigger.GetTriggerState()) << "Analog trigger is on";
|
||||
|
||||
m_output->SetVoltage(2.5);
|
||||
Wait(kDelayTime);
|
||||
output.SetVoltage(2.5);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
EXPECT_TRUE(trigger.GetInWindow())
|
||||
<< "Analog trigger is not in the window (2V, 3V)";
|
||||
EXPECT_FALSE(trigger.GetTriggerState()) << "Analog trigger is on";
|
||||
|
||||
m_output->SetVoltage(4.0);
|
||||
Wait(kDelayTime);
|
||||
output.SetVoltage(4.0);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
EXPECT_FALSE(trigger.GetInWindow())
|
||||
<< "Analog trigger is in the window (2V, 3V)";
|
||||
@@ -84,18 +69,21 @@ TEST_F(AnalogLoopTest, AnalogTriggerWorks) {
|
||||
* Test if we can count the right number of ticks from an analog trigger with
|
||||
* a counter.
|
||||
*/
|
||||
TEST_F(AnalogLoopTest, AnalogTriggerCounterWorks) {
|
||||
AnalogTrigger trigger(m_input);
|
||||
TEST(AnalogLoopTest, AnalogTriggerCounterWorks) {
|
||||
frc::AnalogInput input{TestBench::kFakeAnalogOutputChannel};
|
||||
frc::AnalogOutput output{TestBench::kAnalogOutputChannel};
|
||||
|
||||
frc::AnalogTrigger trigger{&input};
|
||||
trigger.SetLimitsVoltage(2.0, 3.0);
|
||||
|
||||
Counter counter(trigger);
|
||||
frc::Counter counter{trigger};
|
||||
|
||||
// Turn the analog output low and high 50 times
|
||||
for (int32_t i = 0; i < 50; i++) {
|
||||
m_output->SetVoltage(1.0);
|
||||
Wait(kDelayTime);
|
||||
m_output->SetVoltage(4.0);
|
||||
Wait(kDelayTime);
|
||||
output.SetVoltage(1.0);
|
||||
frc::Wait(kDelayTime);
|
||||
output.SetVoltage(4.0);
|
||||
frc::Wait(kDelayTime);
|
||||
}
|
||||
|
||||
// The counter should be 50
|
||||
@@ -107,24 +95,27 @@ static void InterruptHandler(uint32_t interruptAssertedMask, void* param) {
|
||||
*reinterpret_cast<int32_t*>(param) = 12345;
|
||||
}
|
||||
|
||||
TEST_F(AnalogLoopTest, AsynchronusInterruptWorks) {
|
||||
TEST(AnalogLoopTest, AsynchronusInterruptWorks) {
|
||||
frc::AnalogInput input{TestBench::kFakeAnalogOutputChannel};
|
||||
frc::AnalogOutput output{TestBench::kAnalogOutputChannel};
|
||||
|
||||
int32_t param = 0;
|
||||
AnalogTrigger trigger(m_input);
|
||||
frc::AnalogTrigger trigger{&input};
|
||||
trigger.SetLimitsVoltage(2.0, 3.0);
|
||||
|
||||
// Given an interrupt handler that sets an int32_t to 12345
|
||||
std::shared_ptr<AnalogTriggerOutput> triggerOutput =
|
||||
trigger.CreateOutput(AnalogTriggerType::kState);
|
||||
std::shared_ptr<frc::AnalogTriggerOutput> triggerOutput =
|
||||
trigger.CreateOutput(frc::AnalogTriggerType::kState);
|
||||
triggerOutput->RequestInterrupts(InterruptHandler, ¶m);
|
||||
triggerOutput->EnableInterrupts();
|
||||
|
||||
// If the analog output moves from below to above the window
|
||||
m_output->SetVoltage(0.0);
|
||||
Wait(kDelayTime);
|
||||
m_output->SetVoltage(5.0);
|
||||
output.SetVoltage(0.0);
|
||||
frc::Wait(kDelayTime);
|
||||
output.SetVoltage(5.0);
|
||||
triggerOutput->CancelInterrupts();
|
||||
|
||||
// Then the int32_t should be 12345
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_EQ(12345, param) << "The interrupt did not run.";
|
||||
}
|
||||
|
||||
@@ -10,38 +10,25 @@
|
||||
#include "frc/Timer.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
static constexpr double kScale = 270.0;
|
||||
static constexpr double kAngle = 180.0;
|
||||
|
||||
static const double kScale = 270.0;
|
||||
static const double kAngle = 180.0;
|
||||
TEST(AnalogPotentiometerTest, TestInitialSettings) {
|
||||
frc::AnalogOutput m_fakePot{TestBench::kAnalogOutputChannel};
|
||||
frc::AnalogPotentiometer m_pot{TestBench::kFakeAnalogOutputChannel, kScale};
|
||||
|
||||
class AnalogPotentiometerTest : public testing::Test {
|
||||
protected:
|
||||
AnalogOutput* m_fakePot;
|
||||
AnalogPotentiometer* m_pot;
|
||||
|
||||
void SetUp() override {
|
||||
m_fakePot = new AnalogOutput(TestBench::kAnalogOutputChannel);
|
||||
m_pot =
|
||||
new AnalogPotentiometer(TestBench::kFakeAnalogOutputChannel, kScale);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete m_fakePot;
|
||||
delete m_pot;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(AnalogPotentiometerTest, TestInitialSettings) {
|
||||
m_fakePot->SetVoltage(0.0);
|
||||
Wait(0.1_s);
|
||||
EXPECT_NEAR(0.0, m_pot->Get(), 5.0)
|
||||
m_fakePot.SetVoltage(0.0);
|
||||
frc::Wait(100_ms);
|
||||
EXPECT_NEAR(0.0, m_pot.Get(), 5.0)
|
||||
<< "The potentiometer did not initialize to 0.";
|
||||
}
|
||||
|
||||
TEST_F(AnalogPotentiometerTest, TestRangeValues) {
|
||||
m_fakePot->SetVoltage(kAngle / kScale * RobotController::GetVoltage5V());
|
||||
Wait(0.1_s);
|
||||
EXPECT_NEAR(kAngle, m_pot->Get(), 2.0)
|
||||
TEST(AnalogPotentiometerTest, TestRangeValues) {
|
||||
frc::AnalogOutput m_fakePot{TestBench::kAnalogOutputChannel};
|
||||
frc::AnalogPotentiometer m_pot{TestBench::kFakeAnalogOutputChannel, kScale};
|
||||
|
||||
m_fakePot.SetVoltage(kAngle / kScale * frc::RobotController::GetVoltage5V());
|
||||
frc::Wait(100_ms);
|
||||
EXPECT_NEAR(kAngle, m_pot.Get(), 2.0)
|
||||
<< "The potentiometer did not measure the correct angle.";
|
||||
}
|
||||
|
||||
@@ -7,19 +7,18 @@
|
||||
#include "frc/Timer.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static constexpr double kAccelerationTolerance = 0.1;
|
||||
|
||||
/**
|
||||
* There's not much we can automatically test with the on-board accelerometer,
|
||||
* but checking for gravity is probably good enough to tell that it's working.
|
||||
*/
|
||||
TEST(BuiltInAccelerometerTest, Accelerometer) {
|
||||
BuiltInAccelerometer accelerometer;
|
||||
frc::BuiltInAccelerometer accelerometer;
|
||||
|
||||
/* The testbench sometimes shakes a little from a previous test. Give it
|
||||
some time. */
|
||||
Wait(1_s);
|
||||
// The testbench sometimes shakes a little from a previous test. Give it some
|
||||
// time.
|
||||
frc::Wait(1_s);
|
||||
|
||||
ASSERT_NEAR(0.0, accelerometer.GetX(), kAccelerationTolerance);
|
||||
ASSERT_NEAR(1.0, accelerometer.GetY(), kAccelerationTolerance);
|
||||
|
||||
@@ -13,46 +13,26 @@
|
||||
#include "frc/motorcontrol/Victor.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static constexpr auto kMotorDelay = 2.5_s;
|
||||
|
||||
static constexpr auto kMaxPeriod = 2_s;
|
||||
|
||||
class CounterTest : public testing::Test {
|
||||
protected:
|
||||
Counter* m_talonCounter;
|
||||
Counter* m_victorCounter;
|
||||
Counter* m_jaguarCounter;
|
||||
Talon* m_talon;
|
||||
Victor* m_victor;
|
||||
Jaguar* m_jaguar;
|
||||
|
||||
void SetUp() override {
|
||||
m_talonCounter = new Counter(TestBench::kTalonEncoderChannelA);
|
||||
m_victorCounter = new Counter(TestBench::kVictorEncoderChannelA);
|
||||
m_jaguarCounter = new Counter(TestBench::kJaguarEncoderChannelA);
|
||||
m_victor = new Victor(TestBench::kVictorChannel);
|
||||
m_talon = new Talon(TestBench::kTalonChannel);
|
||||
m_jaguar = new Jaguar(TestBench::kJaguarChannel);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete m_talonCounter;
|
||||
delete m_victorCounter;
|
||||
delete m_jaguarCounter;
|
||||
delete m_victor;
|
||||
delete m_talon;
|
||||
delete m_jaguar;
|
||||
}
|
||||
frc::Counter m_talonCounter{TestBench::kTalonEncoderChannelA};
|
||||
frc::Counter m_victorCounter{TestBench::kVictorEncoderChannelA};
|
||||
frc::Counter m_jaguarCounter{TestBench::kJaguarEncoderChannelA};
|
||||
frc::Talon m_talon{TestBench::kVictorChannel};
|
||||
frc::Victor m_victor{TestBench::kTalonChannel};
|
||||
frc::Jaguar m_jaguar{TestBench::kJaguarChannel};
|
||||
|
||||
void Reset() {
|
||||
m_talonCounter->Reset();
|
||||
m_victorCounter->Reset();
|
||||
m_jaguarCounter->Reset();
|
||||
m_talon->Set(0.0);
|
||||
m_victor->Set(0.0);
|
||||
m_jaguar->Set(0.0);
|
||||
m_talonCounter.Reset();
|
||||
m_victorCounter.Reset();
|
||||
m_jaguarCounter.Reset();
|
||||
m_talon.Set(0.0);
|
||||
m_victor.Set(0.0);
|
||||
m_jaguar.Set(0.0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -64,17 +44,17 @@ TEST_F(CounterTest, CountTalon) {
|
||||
Reset();
|
||||
|
||||
/* Run the motor forward and determine if the counter is counting. */
|
||||
m_talon->Set(1.0);
|
||||
Wait(0.5_s);
|
||||
m_talon.Set(1.0);
|
||||
frc::Wait(0.5_s);
|
||||
|
||||
EXPECT_NE(0.0, m_talonCounter->Get()) << "The counter did not count (talon)";
|
||||
EXPECT_NE(0.0, m_talonCounter.Get()) << "The counter did not count (talon)";
|
||||
|
||||
/* Set the motor to 0 and determine if the counter resets to 0. */
|
||||
m_talon->Set(0.0);
|
||||
Wait(0.5_s);
|
||||
m_talonCounter->Reset();
|
||||
m_talon.Set(0.0);
|
||||
frc::Wait(0.5_s);
|
||||
m_talonCounter.Reset();
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, m_talonCounter->Get())
|
||||
EXPECT_FLOAT_EQ(0.0, m_talonCounter.Get())
|
||||
<< "The counter did not restart to 0 (talon)";
|
||||
}
|
||||
|
||||
@@ -82,18 +62,17 @@ TEST_F(CounterTest, CountVictor) {
|
||||
Reset();
|
||||
|
||||
/* Run the motor forward and determine if the counter is counting. */
|
||||
m_victor->Set(1.0);
|
||||
Wait(0.5_s);
|
||||
m_victor.Set(1.0);
|
||||
frc::Wait(0.5_s);
|
||||
|
||||
EXPECT_NE(0.0, m_victorCounter->Get())
|
||||
<< "The counter did not count (victor)";
|
||||
EXPECT_NE(0.0, m_victorCounter.Get()) << "The counter did not count (victor)";
|
||||
|
||||
/* Set the motor to 0 and determine if the counter resets to 0. */
|
||||
m_victor->Set(0.0);
|
||||
Wait(0.5_s);
|
||||
m_victorCounter->Reset();
|
||||
m_victor.Set(0.0);
|
||||
frc::Wait(0.5_s);
|
||||
m_victorCounter.Reset();
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, m_victorCounter->Get())
|
||||
EXPECT_FLOAT_EQ(0.0, m_victorCounter.Get())
|
||||
<< "The counter did not restart to 0 (jaguar)";
|
||||
}
|
||||
|
||||
@@ -101,18 +80,17 @@ TEST_F(CounterTest, CountJaguar) {
|
||||
Reset();
|
||||
|
||||
/* Run the motor forward and determine if the counter is counting. */
|
||||
m_jaguar->Set(1.0);
|
||||
Wait(0.5_s);
|
||||
m_jaguar.Set(1.0);
|
||||
frc::Wait(0.5_s);
|
||||
|
||||
EXPECT_NE(0.0, m_jaguarCounter->Get())
|
||||
<< "The counter did not count (jaguar)";
|
||||
EXPECT_NE(0.0, m_jaguarCounter.Get()) << "The counter did not count (jaguar)";
|
||||
|
||||
/* Set the motor to 0 and determine if the counter resets to 0. */
|
||||
m_jaguar->Set(0.0);
|
||||
Wait(0.5_s);
|
||||
m_jaguarCounter->Reset();
|
||||
m_jaguar.Set(0.0);
|
||||
frc::Wait(0.5_s);
|
||||
m_jaguarCounter.Reset();
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, m_jaguarCounter->Get())
|
||||
EXPECT_FLOAT_EQ(0.0, m_jaguarCounter.Get())
|
||||
<< "The counter did not restart to 0 (jaguar)";
|
||||
}
|
||||
|
||||
@@ -124,17 +102,17 @@ TEST_F(CounterTest, TalonGetStopped) {
|
||||
Reset();
|
||||
|
||||
/* Set the Max Period of the counter and run the motor */
|
||||
m_talonCounter->SetMaxPeriod(kMaxPeriod);
|
||||
m_talon->Set(1.0);
|
||||
Wait(0.5_s);
|
||||
m_talonCounter.SetMaxPeriod(kMaxPeriod);
|
||||
m_talon.Set(1.0);
|
||||
frc::Wait(0.5_s);
|
||||
|
||||
EXPECT_FALSE(m_talonCounter->GetStopped()) << "The counter did not count.";
|
||||
EXPECT_FALSE(m_talonCounter.GetStopped()) << "The counter did not count.";
|
||||
|
||||
/* Stop the motor and wait until the Max Period is exceeded */
|
||||
m_talon->Set(0.0);
|
||||
Wait(kMotorDelay);
|
||||
m_talon.Set(0.0);
|
||||
frc::Wait(kMotorDelay);
|
||||
|
||||
EXPECT_TRUE(m_talonCounter->GetStopped())
|
||||
EXPECT_TRUE(m_talonCounter.GetStopped())
|
||||
<< "The counter did not stop counting.";
|
||||
}
|
||||
|
||||
@@ -142,17 +120,17 @@ TEST_F(CounterTest, VictorGetStopped) {
|
||||
Reset();
|
||||
|
||||
/* Set the Max Period of the counter and run the motor */
|
||||
m_victorCounter->SetMaxPeriod(kMaxPeriod);
|
||||
m_victor->Set(1.0);
|
||||
Wait(0.5_s);
|
||||
m_victorCounter.SetMaxPeriod(kMaxPeriod);
|
||||
m_victor.Set(1.0);
|
||||
frc::Wait(0.5_s);
|
||||
|
||||
EXPECT_FALSE(m_victorCounter->GetStopped()) << "The counter did not count.";
|
||||
EXPECT_FALSE(m_victorCounter.GetStopped()) << "The counter did not count.";
|
||||
|
||||
/* Stop the motor and wait until the Max Period is exceeded */
|
||||
m_victor->Set(0.0);
|
||||
Wait(kMotorDelay);
|
||||
m_victor.Set(0.0);
|
||||
frc::Wait(kMotorDelay);
|
||||
|
||||
EXPECT_TRUE(m_victorCounter->GetStopped())
|
||||
EXPECT_TRUE(m_victorCounter.GetStopped())
|
||||
<< "The counter did not stop counting.";
|
||||
}
|
||||
|
||||
@@ -160,16 +138,16 @@ TEST_F(CounterTest, JaguarGetStopped) {
|
||||
Reset();
|
||||
|
||||
/* Set the Max Period of the counter and run the motor */
|
||||
m_jaguarCounter->SetMaxPeriod(kMaxPeriod);
|
||||
m_jaguar->Set(1.0);
|
||||
Wait(0.5_s);
|
||||
m_jaguarCounter.SetMaxPeriod(kMaxPeriod);
|
||||
m_jaguar.Set(1.0);
|
||||
frc::Wait(0.5_s);
|
||||
|
||||
EXPECT_FALSE(m_jaguarCounter->GetStopped()) << "The counter did not count.";
|
||||
EXPECT_FALSE(m_jaguarCounter.GetStopped()) << "The counter did not count.";
|
||||
|
||||
/* Stop the motor and wait until the Max Period is exceeded */
|
||||
m_jaguar->Set(0.0);
|
||||
Wait(kMotorDelay);
|
||||
m_jaguar.Set(0.0);
|
||||
frc::Wait(kMotorDelay);
|
||||
|
||||
EXPECT_TRUE(m_jaguarCounter->GetStopped())
|
||||
EXPECT_TRUE(m_jaguarCounter.GetStopped())
|
||||
<< "The counter did not stop counting.";
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
#define EXPECT_NEAR_UNITS(val1, val2, eps) \
|
||||
EXPECT_LE(units::math::abs(val1 - val2), eps)
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static constexpr auto kCounterTime = 1_ms;
|
||||
|
||||
static constexpr auto kDelayTime = 100_ms;
|
||||
@@ -33,20 +31,10 @@ static constexpr auto kSynchronousInterruptTimeTolerance = 10_ms;
|
||||
*/
|
||||
class DIOLoopTest : public testing::Test {
|
||||
protected:
|
||||
DigitalInput* m_input;
|
||||
DigitalOutput* m_output;
|
||||
frc::DigitalInput m_input{TestBench::kLoop1InputChannel};
|
||||
frc::DigitalOutput m_output{TestBench::kLoop1OutputChannel};
|
||||
|
||||
void SetUp() override {
|
||||
m_input = new DigitalInput(TestBench::kLoop1InputChannel);
|
||||
m_output = new DigitalOutput(TestBench::kLoop1OutputChannel);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete m_input;
|
||||
delete m_output;
|
||||
}
|
||||
|
||||
void Reset() { m_output->Set(false); }
|
||||
void Reset() { m_output.Set(false); }
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -56,15 +44,15 @@ class DIOLoopTest : public testing::Test {
|
||||
TEST_F(DIOLoopTest, Loop) {
|
||||
Reset();
|
||||
|
||||
m_output->Set(false);
|
||||
Wait(kDelayTime);
|
||||
EXPECT_FALSE(m_input->Get()) << "The digital output was turned off, but "
|
||||
<< "the digital input is on.";
|
||||
m_output.Set(false);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_FALSE(m_input.Get()) << "The digital output was turned off, but "
|
||||
<< "the digital input is on.";
|
||||
|
||||
m_output->Set(true);
|
||||
Wait(kDelayTime);
|
||||
EXPECT_TRUE(m_input->Get()) << "The digital output was turned on, but "
|
||||
<< "the digital input is off.";
|
||||
m_output.Set(true);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_TRUE(m_input.Get()) << "The digital output was turned on, but "
|
||||
<< "the digital input is off.";
|
||||
}
|
||||
/**
|
||||
* Tests to see if the DIO PWM functionality works.
|
||||
@@ -72,43 +60,43 @@ TEST_F(DIOLoopTest, Loop) {
|
||||
TEST_F(DIOLoopTest, DIOPWM) {
|
||||
Reset();
|
||||
|
||||
m_output->Set(false);
|
||||
Wait(kDelayTime);
|
||||
EXPECT_FALSE(m_input->Get()) << "The digital output was turned off, but "
|
||||
<< "the digital input is on.";
|
||||
m_output.Set(false);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_FALSE(m_input.Get()) << "The digital output was turned off, but "
|
||||
<< "the digital input is on.";
|
||||
|
||||
// Set frequency to 2.0 Hz
|
||||
m_output->SetPWMRate(2.0);
|
||||
m_output.SetPWMRate(2.0);
|
||||
// Enable PWM, but leave it off
|
||||
m_output->EnablePWM(0.0);
|
||||
Wait(0.5_s);
|
||||
m_output->UpdateDutyCycle(0.5);
|
||||
m_input->RequestInterrupts();
|
||||
m_input->SetUpSourceEdge(false, true);
|
||||
InterruptableSensorBase::WaitResult result =
|
||||
m_input->WaitForInterrupt(3_s, true);
|
||||
m_output.EnablePWM(0.0);
|
||||
frc::Wait(0.5_s);
|
||||
m_output.UpdateDutyCycle(0.5);
|
||||
m_input.RequestInterrupts();
|
||||
m_input.SetUpSourceEdge(false, true);
|
||||
frc::InterruptableSensorBase::WaitResult result =
|
||||
m_input.WaitForInterrupt(3_s, true);
|
||||
|
||||
Wait(0.5_s);
|
||||
bool firstCycle = m_input->Get();
|
||||
Wait(0.5_s);
|
||||
bool secondCycle = m_input->Get();
|
||||
Wait(0.5_s);
|
||||
bool thirdCycle = m_input->Get();
|
||||
Wait(0.5_s);
|
||||
bool forthCycle = m_input->Get();
|
||||
Wait(0.5_s);
|
||||
bool fifthCycle = m_input->Get();
|
||||
Wait(0.5_s);
|
||||
bool sixthCycle = m_input->Get();
|
||||
Wait(0.5_s);
|
||||
bool seventhCycle = m_input->Get();
|
||||
m_output->DisablePWM();
|
||||
Wait(0.5_s);
|
||||
bool firstAfterStop = m_input->Get();
|
||||
Wait(0.5_s);
|
||||
bool secondAfterStop = m_input->Get();
|
||||
frc::Wait(0.5_s);
|
||||
bool firstCycle = m_input.Get();
|
||||
frc::Wait(0.5_s);
|
||||
bool secondCycle = m_input.Get();
|
||||
frc::Wait(0.5_s);
|
||||
bool thirdCycle = m_input.Get();
|
||||
frc::Wait(0.5_s);
|
||||
bool forthCycle = m_input.Get();
|
||||
frc::Wait(0.5_s);
|
||||
bool fifthCycle = m_input.Get();
|
||||
frc::Wait(0.5_s);
|
||||
bool sixthCycle = m_input.Get();
|
||||
frc::Wait(0.5_s);
|
||||
bool seventhCycle = m_input.Get();
|
||||
m_output.DisablePWM();
|
||||
frc::Wait(0.5_s);
|
||||
bool firstAfterStop = m_input.Get();
|
||||
frc::Wait(0.5_s);
|
||||
bool secondAfterStop = m_input.Get();
|
||||
|
||||
EXPECT_EQ(InterruptableSensorBase::WaitResult::kFallingEdge, result)
|
||||
EXPECT_EQ(frc::InterruptableSensorBase::WaitResult::kFallingEdge, result)
|
||||
<< "WaitForInterrupt was not falling.";
|
||||
|
||||
EXPECT_FALSE(firstCycle) << "Input not low after first delay";
|
||||
@@ -129,16 +117,16 @@ TEST_F(DIOLoopTest, DIOPWM) {
|
||||
TEST_F(DIOLoopTest, FakeCounter) {
|
||||
Reset();
|
||||
|
||||
Counter counter(m_input);
|
||||
frc::Counter counter{&m_input};
|
||||
|
||||
EXPECT_EQ(0, counter.Get()) << "Counter did not initialize to 0.";
|
||||
|
||||
/* Count 100 ticks. The counter value should be 100 after this loop. */
|
||||
for (int32_t i = 0; i < 100; i++) {
|
||||
m_output->Set(true);
|
||||
Wait(kCounterTime);
|
||||
m_output->Set(false);
|
||||
Wait(kCounterTime);
|
||||
for (int32_t i = 0; i < 100; ++i) {
|
||||
m_output.Set(true);
|
||||
frc::Wait(kCounterTime);
|
||||
m_output.Set(false);
|
||||
frc::Wait(kCounterTime);
|
||||
}
|
||||
|
||||
EXPECT_EQ(100, counter.Get()) << "Counter did not count up to 100.";
|
||||
@@ -152,40 +140,40 @@ TEST_F(DIOLoopTest, AsynchronousInterruptWorks) {
|
||||
int32_t param = 0;
|
||||
|
||||
// Given an interrupt handler that sets an int32_t to 12345
|
||||
m_input->RequestInterrupts(InterruptHandler, ¶m);
|
||||
m_input->EnableInterrupts();
|
||||
m_input.RequestInterrupts(InterruptHandler, ¶m);
|
||||
m_input.EnableInterrupts();
|
||||
|
||||
// If the voltage rises
|
||||
m_output->Set(false);
|
||||
m_output->Set(true);
|
||||
m_input->CancelInterrupts();
|
||||
m_output.Set(false);
|
||||
m_output.Set(true);
|
||||
m_input.CancelInterrupts();
|
||||
|
||||
// Then the int32_t should be 12345
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_EQ(12345, param) << "The interrupt did not run.";
|
||||
}
|
||||
|
||||
static void* InterruptTriggerer(void* data) {
|
||||
DigitalOutput* output = static_cast<DigitalOutput*>(data);
|
||||
output->Set(false);
|
||||
Wait(kSynchronousInterruptTime);
|
||||
output->Set(true);
|
||||
auto& output = *static_cast<frc::DigitalOutput*>(data);
|
||||
output.Set(false);
|
||||
frc::Wait(kSynchronousInterruptTime);
|
||||
output.Set(true);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TEST_F(DIOLoopTest, SynchronousInterruptWorks) {
|
||||
// Given a synchronous interrupt
|
||||
m_input->RequestInterrupts();
|
||||
m_input.RequestInterrupts();
|
||||
|
||||
// If we have another thread trigger the interrupt in a few seconds
|
||||
pthread_t interruptTriggererLoop;
|
||||
pthread_create(&interruptTriggererLoop, nullptr, InterruptTriggerer,
|
||||
m_output);
|
||||
&m_output);
|
||||
|
||||
// Then this thread should pause and resume after that number of seconds
|
||||
Timer timer;
|
||||
frc::Timer timer;
|
||||
timer.Start();
|
||||
m_input->WaitForInterrupt(kSynchronousInterruptTime + 1_s);
|
||||
m_input.WaitForInterrupt(kSynchronousInterruptTime + 1_s);
|
||||
EXPECT_NEAR_UNITS(kSynchronousInterruptTime, timer.Get(),
|
||||
kSynchronousInterruptTimeTolerance);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include "frc/Encoder.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
* Tests that configuring inputs to be filtered succeeds.
|
||||
*
|
||||
@@ -19,27 +17,27 @@ using namespace frc;
|
||||
* make sure that the acutal configuration matches.
|
||||
*/
|
||||
TEST(DigitalGlitchFilterTest, BasicTest) {
|
||||
DigitalInput input1(1);
|
||||
DigitalInput input2(2);
|
||||
DigitalInput input3(3);
|
||||
DigitalInput input4(4);
|
||||
Encoder encoder5(5, 6);
|
||||
Counter counter7(7);
|
||||
frc::DigitalInput input1{1};
|
||||
frc::DigitalInput input2{2};
|
||||
frc::DigitalInput input3{3};
|
||||
frc::DigitalInput input4{4};
|
||||
frc::Encoder encoder5{5, 6};
|
||||
frc::Counter counter7{7};
|
||||
|
||||
// Check that we can make a single filter and set the period.
|
||||
DigitalGlitchFilter filter1;
|
||||
frc::DigitalGlitchFilter filter1;
|
||||
filter1.Add(&input1);
|
||||
filter1.SetPeriodNanoSeconds(4200);
|
||||
|
||||
// Check that we can make a second filter with 2 inputs.
|
||||
DigitalGlitchFilter filter2;
|
||||
frc::DigitalGlitchFilter filter2;
|
||||
filter2.Add(&input2);
|
||||
filter2.Add(&input3);
|
||||
filter2.SetPeriodNanoSeconds(97100);
|
||||
|
||||
// Check that we can make a third filter with an input, an encoder, and a
|
||||
// counter.
|
||||
DigitalGlitchFilter filter3;
|
||||
frc::DigitalGlitchFilter filter3;
|
||||
filter3.Add(&input4);
|
||||
filter3.Add(&encoder5);
|
||||
filter3.Add(&counter7);
|
||||
|
||||
@@ -14,20 +14,18 @@
|
||||
#define EXPECT_NEAR_UNITS(val1, val2, eps) \
|
||||
EXPECT_LE(units::math::abs(val1 - val2), eps)
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
* Test if the WaitForData function works
|
||||
*/
|
||||
TEST(DriverStationTest, WaitForData) {
|
||||
units::microsecond_t initialTime(RobotController::GetFPGATime());
|
||||
units::microsecond_t initialTime(frc::RobotController::GetFPGATime());
|
||||
|
||||
// 20ms waiting intervals * 50 = 1s
|
||||
for (int i = 0; i < 50; i++) {
|
||||
DriverStation::GetInstance().WaitForData();
|
||||
frc::DriverStation::GetInstance().WaitForData();
|
||||
}
|
||||
|
||||
units::microsecond_t finalTime(RobotController::GetFPGATime());
|
||||
units::microsecond_t finalTime(frc::RobotController::GetFPGATime());
|
||||
|
||||
EXPECT_NEAR_UNITS(1_s, finalTime - initialTime, 200_ms);
|
||||
}
|
||||
|
||||
@@ -13,41 +13,24 @@
|
||||
#include "frc/Timer.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static constexpr auto kDelayTime = 1_ms;
|
||||
|
||||
class FakeEncoderTest : public testing::Test {
|
||||
protected:
|
||||
DigitalOutput* m_outputA;
|
||||
DigitalOutput* m_outputB;
|
||||
AnalogOutput* m_indexOutput;
|
||||
frc::DigitalOutput m_outputA{TestBench::kLoop2OutputChannel};
|
||||
frc::DigitalOutput m_outputB{TestBench::kLoop1OutputChannel};
|
||||
frc::AnalogOutput m_indexOutput{TestBench::kAnalogOutputChannel};
|
||||
|
||||
Encoder* m_encoder;
|
||||
AnalogTrigger* m_indexAnalogTrigger;
|
||||
std::shared_ptr<AnalogTriggerOutput> m_indexAnalogTriggerOutput;
|
||||
frc::Encoder m_encoder{TestBench::kLoop1InputChannel,
|
||||
TestBench::kLoop2InputChannel};
|
||||
frc::AnalogTrigger m_indexAnalogTrigger{TestBench::kFakeAnalogOutputChannel};
|
||||
std::shared_ptr<frc::AnalogTriggerOutput> m_indexAnalogTriggerOutput =
|
||||
m_indexAnalogTrigger.CreateOutput(frc::AnalogTriggerType::kState);
|
||||
|
||||
void SetUp() override {
|
||||
m_outputA = new DigitalOutput(TestBench::kLoop2OutputChannel);
|
||||
m_outputB = new DigitalOutput(TestBench::kLoop1OutputChannel);
|
||||
m_indexOutput = new AnalogOutput(TestBench::kAnalogOutputChannel);
|
||||
m_outputA->Set(false);
|
||||
m_outputB->Set(false);
|
||||
m_encoder = new Encoder(TestBench::kLoop1InputChannel,
|
||||
TestBench::kLoop2InputChannel);
|
||||
m_indexAnalogTrigger =
|
||||
new AnalogTrigger(TestBench::kFakeAnalogOutputChannel);
|
||||
m_indexAnalogTrigger->SetLimitsVoltage(2.0, 3.0);
|
||||
m_indexAnalogTriggerOutput =
|
||||
m_indexAnalogTrigger->CreateOutput(AnalogTriggerType::kState);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete m_outputA;
|
||||
delete m_outputB;
|
||||
delete m_indexOutput;
|
||||
delete m_encoder;
|
||||
delete m_indexAnalogTrigger;
|
||||
FakeEncoderTest() {
|
||||
m_outputA.Set(false);
|
||||
m_outputB.Set(false);
|
||||
m_indexAnalogTrigger.SetLimitsVoltage(2.0, 3.0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,25 +39,25 @@ class FakeEncoderTest : public testing::Test {
|
||||
*/
|
||||
void Simulate100QuadratureTicks() {
|
||||
for (int32_t i = 0; i < 100; i++) {
|
||||
m_outputA->Set(true);
|
||||
Wait(kDelayTime);
|
||||
m_outputB->Set(true);
|
||||
Wait(kDelayTime);
|
||||
m_outputA->Set(false);
|
||||
Wait(kDelayTime);
|
||||
m_outputB->Set(false);
|
||||
Wait(kDelayTime);
|
||||
m_outputA.Set(true);
|
||||
frc::Wait(kDelayTime);
|
||||
m_outputB.Set(true);
|
||||
frc::Wait(kDelayTime);
|
||||
m_outputA.Set(false);
|
||||
frc::Wait(kDelayTime);
|
||||
m_outputB.Set(false);
|
||||
frc::Wait(kDelayTime);
|
||||
}
|
||||
}
|
||||
|
||||
void SetIndexHigh() {
|
||||
m_indexOutput->SetVoltage(5.0);
|
||||
Wait(kDelayTime);
|
||||
m_indexOutput.SetVoltage(5.0);
|
||||
frc::Wait(kDelayTime);
|
||||
}
|
||||
|
||||
void SetIndexLow() {
|
||||
m_indexOutput->SetVoltage(0.0);
|
||||
Wait(kDelayTime);
|
||||
m_indexOutput.SetVoltage(0.0);
|
||||
frc::Wait(kDelayTime);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -82,79 +65,79 @@ class FakeEncoderTest : public testing::Test {
|
||||
* Test the encoder by reseting it to 0 and reading the value.
|
||||
*/
|
||||
TEST_F(FakeEncoderTest, TestDefaultState) {
|
||||
EXPECT_FLOAT_EQ(0.0, m_encoder->Get()) << "The encoder did not start at 0.";
|
||||
EXPECT_DOUBLE_EQ(0.0, m_encoder.Get()) << "The encoder did not start at 0.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the encoder by setting the digital outputs and reading the value.
|
||||
*/
|
||||
TEST_F(FakeEncoderTest, TestCountUp) {
|
||||
m_encoder->Reset();
|
||||
m_encoder.Reset();
|
||||
Simulate100QuadratureTicks();
|
||||
|
||||
EXPECT_FLOAT_EQ(100.0, m_encoder->Get()) << "Encoder did not count to 100.";
|
||||
EXPECT_DOUBLE_EQ(100.0, m_encoder.Get()) << "Encoder did not count to 100.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the encoder can stay reset while the index source is high
|
||||
*/
|
||||
TEST_F(FakeEncoderTest, TestResetWhileHigh) {
|
||||
m_encoder->SetIndexSource(*m_indexAnalogTriggerOutput,
|
||||
Encoder::IndexingType::kResetWhileHigh);
|
||||
m_encoder.SetIndexSource(*m_indexAnalogTriggerOutput,
|
||||
frc::Encoder::IndexingType::kResetWhileHigh);
|
||||
|
||||
SetIndexLow();
|
||||
Simulate100QuadratureTicks();
|
||||
SetIndexHigh();
|
||||
EXPECT_EQ(0, m_encoder->Get());
|
||||
EXPECT_EQ(0, m_encoder.Get());
|
||||
|
||||
Simulate100QuadratureTicks();
|
||||
EXPECT_EQ(0, m_encoder->Get());
|
||||
EXPECT_EQ(0, m_encoder.Get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the encoder can reset when the index source goes from low to high
|
||||
*/
|
||||
TEST_F(FakeEncoderTest, TestResetOnRisingEdge) {
|
||||
m_encoder->SetIndexSource(*m_indexAnalogTriggerOutput,
|
||||
Encoder::IndexingType::kResetOnRisingEdge);
|
||||
m_encoder.SetIndexSource(*m_indexAnalogTriggerOutput,
|
||||
frc::Encoder::IndexingType::kResetOnRisingEdge);
|
||||
|
||||
SetIndexLow();
|
||||
Simulate100QuadratureTicks();
|
||||
SetIndexHigh();
|
||||
EXPECT_EQ(0, m_encoder->Get());
|
||||
EXPECT_EQ(0, m_encoder.Get());
|
||||
|
||||
Simulate100QuadratureTicks();
|
||||
EXPECT_EQ(100, m_encoder->Get());
|
||||
EXPECT_EQ(100, m_encoder.Get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the encoder can stay reset while the index source is low
|
||||
*/
|
||||
TEST_F(FakeEncoderTest, TestResetWhileLow) {
|
||||
m_encoder->SetIndexSource(*m_indexAnalogTriggerOutput,
|
||||
Encoder::IndexingType::kResetWhileLow);
|
||||
m_encoder.SetIndexSource(*m_indexAnalogTriggerOutput,
|
||||
frc::Encoder::IndexingType::kResetWhileLow);
|
||||
|
||||
SetIndexHigh();
|
||||
Simulate100QuadratureTicks();
|
||||
SetIndexLow();
|
||||
EXPECT_EQ(0, m_encoder->Get());
|
||||
EXPECT_EQ(0, m_encoder.Get());
|
||||
|
||||
Simulate100QuadratureTicks();
|
||||
EXPECT_EQ(0, m_encoder->Get());
|
||||
EXPECT_EQ(0, m_encoder.Get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the encoder can reset when the index source goes from high to low
|
||||
*/
|
||||
TEST_F(FakeEncoderTest, TestResetOnFallingEdge) {
|
||||
m_encoder->SetIndexSource(*m_indexAnalogTriggerOutput,
|
||||
Encoder::IndexingType::kResetOnFallingEdge);
|
||||
m_encoder.SetIndexSource(*m_indexAnalogTriggerOutput,
|
||||
frc::Encoder::IndexingType::kResetOnFallingEdge);
|
||||
|
||||
SetIndexHigh();
|
||||
Simulate100QuadratureTicks();
|
||||
SetIndexLow();
|
||||
EXPECT_EQ(0, m_encoder->Get());
|
||||
EXPECT_EQ(0, m_encoder.Get());
|
||||
|
||||
Simulate100QuadratureTicks();
|
||||
EXPECT_EQ(100, m_encoder->Get());
|
||||
EXPECT_EQ(100, m_encoder.Get());
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
int ret = RUN_ALL_TESTS();
|
||||
return ret;
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -17,8 +17,6 @@
|
||||
#include "frc/motorcontrol/Victor.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
enum MotorEncoderTestType { TEST_VICTOR, TEST_JAGUAR, TEST_TALON };
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, MotorEncoderTestType const& type) {
|
||||
@@ -45,38 +43,38 @@ static constexpr auto kMotorTime = 0.5_s;
|
||||
*/
|
||||
class MotorEncoderTest : public testing::TestWithParam<MotorEncoderTestType> {
|
||||
protected:
|
||||
MotorController* m_motorController;
|
||||
Encoder* m_encoder;
|
||||
LinearFilter<double>* m_filter;
|
||||
frc::MotorController* m_motorController;
|
||||
frc::Encoder* m_encoder;
|
||||
frc::LinearFilter<double>* m_filter;
|
||||
|
||||
void SetUp() override {
|
||||
MotorEncoderTest() {
|
||||
switch (GetParam()) {
|
||||
case TEST_VICTOR:
|
||||
m_motorController = new Victor(TestBench::kVictorChannel);
|
||||
m_encoder = new Encoder(TestBench::kVictorEncoderChannelA,
|
||||
TestBench::kVictorEncoderChannelB);
|
||||
m_motorController = new frc::Victor(TestBench::kVictorChannel);
|
||||
m_encoder = new frc::Encoder(TestBench::kVictorEncoderChannelA,
|
||||
TestBench::kVictorEncoderChannelB);
|
||||
break;
|
||||
|
||||
case TEST_JAGUAR:
|
||||
m_motorController = new Jaguar(TestBench::kJaguarChannel);
|
||||
m_encoder = new Encoder(TestBench::kJaguarEncoderChannelA,
|
||||
TestBench::kJaguarEncoderChannelB);
|
||||
m_motorController = new frc::Jaguar(TestBench::kJaguarChannel);
|
||||
m_encoder = new frc::Encoder(TestBench::kJaguarEncoderChannelA,
|
||||
TestBench::kJaguarEncoderChannelB);
|
||||
break;
|
||||
|
||||
case TEST_TALON:
|
||||
m_motorController = new Talon(TestBench::kTalonChannel);
|
||||
m_encoder = new Encoder(TestBench::kTalonEncoderChannelA,
|
||||
TestBench::kTalonEncoderChannelB);
|
||||
m_motorController = new frc::Talon(TestBench::kTalonChannel);
|
||||
m_encoder = new frc::Encoder(TestBench::kTalonEncoderChannelA,
|
||||
TestBench::kTalonEncoderChannelB);
|
||||
break;
|
||||
}
|
||||
m_filter =
|
||||
new LinearFilter<double>(LinearFilter<double>::MovingAverage(50));
|
||||
m_filter = new frc::LinearFilter<double>(
|
||||
frc::LinearFilter<double>::MovingAverage(50));
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete m_motorController;
|
||||
delete m_encoder;
|
||||
~MotorEncoderTest() {
|
||||
delete m_filter;
|
||||
delete m_encoder;
|
||||
delete m_motorController;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
@@ -94,7 +92,7 @@ TEST_P(MotorEncoderTest, Increment) {
|
||||
|
||||
/* Drive the motor controller briefly to move the encoder */
|
||||
m_motorController->Set(0.2f);
|
||||
Wait(kMotorTime);
|
||||
frc::Wait(kMotorTime);
|
||||
m_motorController->Set(0.0);
|
||||
|
||||
/* The encoder should be positive now */
|
||||
@@ -110,7 +108,7 @@ TEST_P(MotorEncoderTest, Decrement) {
|
||||
|
||||
/* Drive the motor controller briefly to move the encoder */
|
||||
m_motorController->Set(-0.2);
|
||||
Wait(kMotorTime);
|
||||
frc::Wait(kMotorTime);
|
||||
m_motorController->Set(0.0);
|
||||
|
||||
/* The encoder should be positive now */
|
||||
@@ -125,12 +123,12 @@ TEST_P(MotorEncoderTest, ClampSpeed) {
|
||||
Reset();
|
||||
|
||||
m_motorController->Set(2.0);
|
||||
Wait(kMotorTime);
|
||||
frc::Wait(kMotorTime);
|
||||
|
||||
EXPECT_FLOAT_EQ(1.0, m_motorController->Get());
|
||||
|
||||
m_motorController->Set(-2.0);
|
||||
Wait(kMotorTime);
|
||||
frc::Wait(kMotorTime);
|
||||
|
||||
EXPECT_FLOAT_EQ(-1.0, m_motorController->Get());
|
||||
}
|
||||
@@ -152,7 +150,7 @@ TEST_P(MotorEncoderTest, PositionPIDController) {
|
||||
m_motorController->Set(std::clamp(speed, -0.2, 0.2));
|
||||
}};
|
||||
pidRunner.StartPeriodic(pidController.GetPeriod());
|
||||
Wait(10_s);
|
||||
frc::Wait(10_s);
|
||||
pidRunner.Stop();
|
||||
|
||||
RecordProperty("PIDError", pidController.GetPositionError());
|
||||
@@ -179,7 +177,7 @@ TEST_P(MotorEncoderTest, VelocityPIDController) {
|
||||
m_motorController->Set(std::clamp(speed, -0.3, 0.3));
|
||||
}};
|
||||
pidRunner.StartPeriodic(pidController.GetPeriod());
|
||||
Wait(10_s);
|
||||
frc::Wait(10_s);
|
||||
pidRunner.Stop();
|
||||
RecordProperty("PIDError", pidController.GetPositionError());
|
||||
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include "frc/motorcontrol/Victor.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
enum MotorInvertingTestType { TEST_VICTOR, TEST_JAGUAR, TEST_TALON };
|
||||
|
||||
static constexpr double kMotorSpeed = 0.15;
|
||||
@@ -37,34 +35,34 @@ std::ostream& operator<<(std::ostream& os, MotorInvertingTestType const& type) {
|
||||
class MotorInvertingTest
|
||||
: public testing::TestWithParam<MotorInvertingTestType> {
|
||||
protected:
|
||||
MotorController* m_motorController;
|
||||
Encoder* m_encoder;
|
||||
frc::MotorController* m_motorController;
|
||||
frc::Encoder* m_encoder;
|
||||
|
||||
void SetUp() override {
|
||||
MotorInvertingTest() {
|
||||
switch (GetParam()) {
|
||||
case TEST_VICTOR:
|
||||
m_motorController = new Victor(TestBench::kVictorChannel);
|
||||
m_encoder = new Encoder(TestBench::kVictorEncoderChannelA,
|
||||
TestBench::kVictorEncoderChannelB);
|
||||
m_motorController = new frc::Victor(TestBench::kVictorChannel);
|
||||
m_encoder = new frc::Encoder(TestBench::kVictorEncoderChannelA,
|
||||
TestBench::kVictorEncoderChannelB);
|
||||
break;
|
||||
|
||||
case TEST_JAGUAR:
|
||||
m_motorController = new Jaguar(TestBench::kJaguarChannel);
|
||||
m_encoder = new Encoder(TestBench::kJaguarEncoderChannelA,
|
||||
TestBench::kJaguarEncoderChannelB);
|
||||
m_motorController = new frc::Jaguar(TestBench::kJaguarChannel);
|
||||
m_encoder = new frc::Encoder(TestBench::kJaguarEncoderChannelA,
|
||||
TestBench::kJaguarEncoderChannelB);
|
||||
break;
|
||||
|
||||
case TEST_TALON:
|
||||
m_motorController = new Talon(TestBench::kTalonChannel);
|
||||
m_encoder = new Encoder(TestBench::kTalonEncoderChannelA,
|
||||
TestBench::kTalonEncoderChannelB);
|
||||
m_motorController = new frc::Talon(TestBench::kTalonChannel);
|
||||
m_encoder = new frc::Encoder(TestBench::kTalonEncoderChannelA,
|
||||
TestBench::kTalonEncoderChannelB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete m_motorController;
|
||||
~MotorInvertingTest() {
|
||||
delete m_encoder;
|
||||
delete m_motorController;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
@@ -79,13 +77,13 @@ TEST_P(MotorInvertingTest, InvertingPositive) {
|
||||
|
||||
m_motorController->Set(kMotorSpeed);
|
||||
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
bool initDirection = m_encoder->GetDirection();
|
||||
m_motorController->SetInverted(true);
|
||||
m_motorController->Set(kMotorSpeed);
|
||||
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
EXPECT_TRUE(m_encoder->GetDirection() != initDirection)
|
||||
<< "Inverting with Positive value does not change direction";
|
||||
@@ -99,13 +97,13 @@ TEST_P(MotorInvertingTest, InvertingNegative) {
|
||||
m_motorController->SetInverted(false);
|
||||
m_motorController->Set(-kMotorSpeed);
|
||||
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
bool initDirection = m_encoder->GetDirection();
|
||||
m_motorController->SetInverted(true);
|
||||
m_motorController->Set(-kMotorSpeed);
|
||||
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
EXPECT_TRUE(m_encoder->GetDirection() != initDirection)
|
||||
<< "Inverting with Negative value does not change direction";
|
||||
@@ -119,13 +117,13 @@ TEST_P(MotorInvertingTest, InvertingSwitchingPosToNeg) {
|
||||
m_motorController->SetInverted(false);
|
||||
m_motorController->Set(kMotorSpeed);
|
||||
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
bool initDirection = m_encoder->GetDirection();
|
||||
m_motorController->SetInverted(true);
|
||||
m_motorController->Set(-kMotorSpeed);
|
||||
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
EXPECT_TRUE(m_encoder->GetDirection() == initDirection)
|
||||
<< "Inverting with Switching value does change direction";
|
||||
@@ -139,13 +137,13 @@ TEST_P(MotorInvertingTest, InvertingSwitchingNegToPos) {
|
||||
m_motorController->SetInverted(false);
|
||||
m_motorController->Set(-kMotorSpeed);
|
||||
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
bool initDirection = m_encoder->GetDirection();
|
||||
m_motorController->SetInverted(true);
|
||||
m_motorController->Set(kMotorSpeed);
|
||||
|
||||
Wait(kDelayTime);
|
||||
frc::Wait(kDelayTime);
|
||||
|
||||
EXPECT_TRUE(m_encoder->GetDirection() == initDirection)
|
||||
<< "Inverting with Switching value does change direction";
|
||||
|
||||
@@ -4,14 +4,12 @@
|
||||
|
||||
#include "frc/Notifier.h" // NOLINT(build/include_order)
|
||||
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "TestBench.h"
|
||||
#include "frc/Timer.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
unsigned notifierCounter;
|
||||
|
||||
void notifierHandler(void*) {
|
||||
@@ -22,21 +20,20 @@ void notifierHandler(void*) {
|
||||
* Test if the Wait function works
|
||||
*/
|
||||
TEST(NotifierTest, DISABLED_TestTimerNotifications) {
|
||||
wpi::outs() << "NotifierTest...\n";
|
||||
fmt::print("NotifierTest...\n");
|
||||
notifierCounter = 0;
|
||||
wpi::outs() << "notifier(notifierHandler, nullptr)...\n";
|
||||
Notifier notifier(notifierHandler, nullptr);
|
||||
wpi::outs() << "Start Periodic...\n";
|
||||
fmt::print("notifier(notifierHandler, nullptr)...\n");
|
||||
frc::Notifier notifier(notifierHandler, nullptr);
|
||||
fmt::print("Start Periodic...\n");
|
||||
notifier.StartPeriodic(1_s);
|
||||
|
||||
wpi::outs() << "Wait...\n";
|
||||
Wait(10.5_s);
|
||||
wpi::outs() << "...Wait\n";
|
||||
fmt::print("Wait...\n");
|
||||
frc::Wait(10.5_s);
|
||||
fmt::print("...Wait\n");
|
||||
|
||||
EXPECT_EQ(10u, notifierCounter)
|
||||
<< "Received " << notifierCounter << " notifications in 10.5 seconds";
|
||||
wpi::outs() << "Received " << notifierCounter
|
||||
<< " notifications in 10.5 seconds";
|
||||
fmt::print("Received {} notifications in 10.5 seconds", notifierCounter);
|
||||
|
||||
wpi::outs() << "...NotifierTest\n";
|
||||
fmt::print("...NotifierTest\n");
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include "frc/Timer.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/* The PCM switches the compressor up to a couple seconds after the pressure
|
||||
switch changes. */
|
||||
static constexpr auto kCompressorDelayTime = 3_s;
|
||||
@@ -28,34 +26,17 @@ static const double kCompressorOffVoltage = 1.68;
|
||||
|
||||
class PCMTest : public testing::Test {
|
||||
protected:
|
||||
Compressor* m_compressor;
|
||||
frc::Compressor m_compressor;
|
||||
|
||||
DigitalOutput* m_fakePressureSwitch;
|
||||
AnalogInput* m_fakeCompressor;
|
||||
DoubleSolenoid* m_doubleSolenoid;
|
||||
DigitalInput *m_fakeSolenoid1, *m_fakeSolenoid2;
|
||||
|
||||
void SetUp() override {
|
||||
m_compressor = new Compressor();
|
||||
|
||||
m_fakePressureSwitch =
|
||||
new DigitalOutput(TestBench::kFakePressureSwitchChannel);
|
||||
m_fakeCompressor = new AnalogInput(TestBench::kFakeCompressorChannel);
|
||||
m_fakeSolenoid1 = new DigitalInput(TestBench::kFakeSolenoid1Channel);
|
||||
m_fakeSolenoid2 = new DigitalInput(TestBench::kFakeSolenoid2Channel);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete m_compressor;
|
||||
delete m_fakePressureSwitch;
|
||||
delete m_fakeCompressor;
|
||||
delete m_fakeSolenoid1;
|
||||
delete m_fakeSolenoid2;
|
||||
}
|
||||
frc::DigitalOutput m_fakePressureSwitch{
|
||||
TestBench::kFakePressureSwitchChannel};
|
||||
frc::AnalogInput m_fakeCompressor{TestBench::kFakeCompressorChannel};
|
||||
frc::DigitalInput m_fakeSolenoid1{TestBench::kFakeSolenoid1Channel};
|
||||
frc::DigitalInput m_fakeSolenoid2{TestBench::kFakeSolenoid2Channel};
|
||||
|
||||
void Reset() {
|
||||
m_compressor->Stop();
|
||||
m_fakePressureSwitch->Set(false);
|
||||
m_compressor.Stop();
|
||||
m_fakePressureSwitch.Set(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -65,18 +46,18 @@ class PCMTest : public testing::Test {
|
||||
TEST_F(PCMTest, PressureSwitch) {
|
||||
Reset();
|
||||
|
||||
m_compressor->SetClosedLoopControl(true);
|
||||
m_compressor.SetClosedLoopControl(true);
|
||||
|
||||
// Turn on the compressor
|
||||
m_fakePressureSwitch->Set(true);
|
||||
Wait(kCompressorDelayTime);
|
||||
EXPECT_NEAR(kCompressorOnVoltage, m_fakeCompressor->GetVoltage(), 0.5)
|
||||
m_fakePressureSwitch.Set(true);
|
||||
frc::Wait(kCompressorDelayTime);
|
||||
EXPECT_NEAR(kCompressorOnVoltage, m_fakeCompressor.GetVoltage(), 0.5)
|
||||
<< "Compressor did not turn on when the pressure switch turned on.";
|
||||
|
||||
// Turn off the compressor
|
||||
m_fakePressureSwitch->Set(false);
|
||||
Wait(kCompressorDelayTime);
|
||||
EXPECT_NEAR(kCompressorOffVoltage, m_fakeCompressor->GetVoltage(), 0.5)
|
||||
m_fakePressureSwitch.Set(false);
|
||||
frc::Wait(kCompressorDelayTime);
|
||||
EXPECT_NEAR(kCompressorOffVoltage, m_fakeCompressor.GetVoltage(), 0.5)
|
||||
<< "Compressor did not turn off when the pressure switch turned off.";
|
||||
}
|
||||
|
||||
@@ -85,42 +66,42 @@ TEST_F(PCMTest, PressureSwitch) {
|
||||
*/
|
||||
TEST_F(PCMTest, Solenoid) {
|
||||
Reset();
|
||||
Solenoid solenoid1(TestBench::kSolenoidChannel1);
|
||||
Solenoid solenoid2(TestBench::kSolenoidChannel2);
|
||||
frc::Solenoid solenoid1{TestBench::kSolenoidChannel1};
|
||||
frc::Solenoid solenoid2{TestBench::kSolenoidChannel2};
|
||||
|
||||
// Turn both solenoids off
|
||||
solenoid1.Set(false);
|
||||
solenoid2.Set(false);
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn off";
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_FALSE(solenoid1.Get()) << "Solenoid #1 did not read off";
|
||||
EXPECT_FALSE(solenoid2.Get()) << "Solenoid #2 did not read off";
|
||||
|
||||
// Turn one solenoid on and one off
|
||||
solenoid1.Set(true);
|
||||
solenoid2.Set(false);
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_TRUE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn off";
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_TRUE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_TRUE(solenoid1.Get()) << "Solenoid #1 did not read on";
|
||||
EXPECT_FALSE(solenoid2.Get()) << "Solenoid #2 did not read off";
|
||||
|
||||
// Turn one solenoid on and one off
|
||||
solenoid1.Set(false);
|
||||
solenoid2.Set(true);
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_FALSE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn on";
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_FALSE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn on";
|
||||
EXPECT_FALSE(solenoid1.Get()) << "Solenoid #1 did not read off";
|
||||
EXPECT_TRUE(solenoid2.Get()) << "Solenoid #2 did not read on";
|
||||
|
||||
// Turn both on
|
||||
solenoid1.Set(true);
|
||||
solenoid2.Set(true);
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_FALSE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn on";
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_FALSE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn on";
|
||||
EXPECT_TRUE(solenoid1.Get()) << "Solenoid #1 did not read on";
|
||||
EXPECT_TRUE(solenoid2.Get()) << "Solenoid #2 did not read on";
|
||||
}
|
||||
@@ -130,42 +111,42 @@ TEST_F(PCMTest, Solenoid) {
|
||||
* with the DoubleSolenoid class.
|
||||
*/
|
||||
TEST_F(PCMTest, DoubleSolenoid) {
|
||||
DoubleSolenoid solenoid(TestBench::kSolenoidChannel1,
|
||||
TestBench::kSolenoidChannel2);
|
||||
frc::DoubleSolenoid solenoid{TestBench::kSolenoidChannel1,
|
||||
TestBench::kSolenoidChannel2};
|
||||
|
||||
solenoid.Set(DoubleSolenoid::kOff);
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_TRUE(solenoid.Get() == DoubleSolenoid::kOff)
|
||||
solenoid.Set(frc::DoubleSolenoid::kOff);
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_TRUE(solenoid.Get() == frc::DoubleSolenoid::kOff)
|
||||
<< "Solenoid does not read off";
|
||||
|
||||
solenoid.Set(DoubleSolenoid::kForward);
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_TRUE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_TRUE(solenoid.Get() == DoubleSolenoid::kForward)
|
||||
solenoid.Set(frc::DoubleSolenoid::kForward);
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_TRUE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_TRUE(solenoid.Get() == frc::DoubleSolenoid::kForward)
|
||||
<< "Solenoid does not read forward";
|
||||
|
||||
solenoid.Set(DoubleSolenoid::kReverse);
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_FALSE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn on";
|
||||
EXPECT_TRUE(solenoid.Get() == DoubleSolenoid::kReverse)
|
||||
solenoid.Set(frc::DoubleSolenoid::kReverse);
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_FALSE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn on";
|
||||
EXPECT_TRUE(solenoid.Get() == frc::DoubleSolenoid::kReverse)
|
||||
<< "Solenoid does not read reverse";
|
||||
}
|
||||
|
||||
TEST_F(PCMTest, OneShot) {
|
||||
Reset();
|
||||
Solenoid solenoid1(TestBench::kSolenoidChannel1);
|
||||
Solenoid solenoid2(TestBench::kSolenoidChannel2);
|
||||
frc::Solenoid solenoid1{TestBench::kSolenoidChannel1};
|
||||
frc::Solenoid solenoid2{TestBench::kSolenoidChannel2};
|
||||
|
||||
// Turn both solenoids off
|
||||
solenoid1.Set(false);
|
||||
solenoid2.Set(false);
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn off";
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_FALSE(solenoid1.Get()) << "Solenoid #1 did not read off";
|
||||
EXPECT_FALSE(solenoid2.Get()) << "Solenoid #2 did not read off";
|
||||
|
||||
@@ -173,14 +154,14 @@ TEST_F(PCMTest, OneShot) {
|
||||
solenoid1.SetPulseDuration(2 * kSolenoidDelayTime);
|
||||
solenoid2.Set(false);
|
||||
solenoid1.StartPulse();
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_TRUE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn off";
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_TRUE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_TRUE(solenoid1.Get()) << "Solenoid #1 did not read on";
|
||||
EXPECT_FALSE(solenoid2.Get()) << "Solenoid #2 did not read off";
|
||||
Wait(2 * kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn off";
|
||||
frc::Wait(2 * kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_FALSE(solenoid1.Get()) << "Solenoid #1 did not read off";
|
||||
EXPECT_FALSE(solenoid2.Get()) << "Solenoid #2 did not read off";
|
||||
|
||||
@@ -188,14 +169,14 @@ TEST_F(PCMTest, OneShot) {
|
||||
solenoid1.Set(false);
|
||||
solenoid2.SetPulseDuration(2 * kSolenoidDelayTime);
|
||||
solenoid2.StartPulse();
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_FALSE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn on";
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_FALSE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn on";
|
||||
EXPECT_FALSE(solenoid1.Get()) << "Solenoid #1 did not read off";
|
||||
EXPECT_TRUE(solenoid2.Get()) << "Solenoid #2 did not read on";
|
||||
Wait(2 * kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn off";
|
||||
frc::Wait(2 * kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_FALSE(solenoid1.Get()) << "Solenoid #1 did not read off";
|
||||
EXPECT_FALSE(solenoid2.Get()) << "Solenoid #2 did not read off";
|
||||
|
||||
@@ -204,14 +185,14 @@ TEST_F(PCMTest, OneShot) {
|
||||
solenoid2.SetPulseDuration(2 * kSolenoidDelayTime);
|
||||
solenoid1.StartPulse();
|
||||
solenoid2.StartPulse();
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_FALSE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn on";
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_FALSE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn on";
|
||||
EXPECT_TRUE(solenoid1.Get()) << "Solenoid #1 did not read on";
|
||||
EXPECT_TRUE(solenoid2.Get()) << "Solenoid #2 did not read on";
|
||||
Wait(2 * kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn off";
|
||||
frc::Wait(2 * kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_FALSE(solenoid1.Get()) << "Solenoid #1 did not read off";
|
||||
EXPECT_FALSE(solenoid2.Get()) << "Solenoid #2 did not read off";
|
||||
|
||||
@@ -220,19 +201,19 @@ TEST_F(PCMTest, OneShot) {
|
||||
solenoid2.SetPulseDuration(2.5 * kSolenoidDelayTime);
|
||||
solenoid1.StartPulse();
|
||||
solenoid2.StartPulse();
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_FALSE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn on";
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_FALSE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn on";
|
||||
EXPECT_FALSE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn on";
|
||||
EXPECT_TRUE(solenoid1.Get()) << "Solenoid #1 did not read on";
|
||||
EXPECT_TRUE(solenoid2.Get()) << "Solenoid #2 did not read on";
|
||||
Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_FALSE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn on";
|
||||
frc::Wait(kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_FALSE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn on";
|
||||
EXPECT_FALSE(solenoid1.Get()) << "Solenoid #1 did not read off";
|
||||
EXPECT_TRUE(solenoid2.Get()) << "Solenoid #2 did not read on";
|
||||
Wait(2 * kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1->Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2->Get()) << "Solenoid #2 did not turn off";
|
||||
frc::Wait(2 * kSolenoidDelayTime);
|
||||
EXPECT_TRUE(m_fakeSolenoid1.Get()) << "Solenoid #1 did not turn off";
|
||||
EXPECT_TRUE(m_fakeSolenoid2.Get()) << "Solenoid #2 did not turn off";
|
||||
EXPECT_FALSE(solenoid1.Get()) << "Solenoid #1 did not read off";
|
||||
EXPECT_FALSE(solenoid2.Get()) << "Solenoid #2 did not read off";
|
||||
}
|
||||
|
||||
@@ -9,35 +9,15 @@
|
||||
|
||||
#include "TestBench.h"
|
||||
#include "frc/Timer.h"
|
||||
#include "frc/motorcontrol/Jaguar.h"
|
||||
#include "frc/motorcontrol/Talon.h"
|
||||
#include "frc/motorcontrol/Victor.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static constexpr auto kMotorTime = 0.25_s;
|
||||
|
||||
class PowerDistributionPanelTest : public testing::Test {
|
||||
protected:
|
||||
PowerDistributionPanel* m_pdp;
|
||||
Talon* m_talon;
|
||||
Victor* m_victor;
|
||||
Jaguar* m_jaguar;
|
||||
|
||||
void SetUp() override {
|
||||
m_pdp = new PowerDistributionPanel();
|
||||
m_talon = new Talon(TestBench::kTalonChannel);
|
||||
m_victor = new Victor(TestBench::kVictorChannel);
|
||||
m_jaguar = new Jaguar(TestBench::kJaguarChannel);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete m_pdp;
|
||||
delete m_talon;
|
||||
delete m_victor;
|
||||
delete m_jaguar;
|
||||
}
|
||||
frc::PowerDistributionPanel m_pdp;
|
||||
frc::Talon m_talon{TestBench::kTalonChannel};
|
||||
};
|
||||
|
||||
TEST_F(PowerDistributionPanelTest, CheckRepeatedCalls) {
|
||||
@@ -45,28 +25,28 @@ TEST_F(PowerDistributionPanelTest, CheckRepeatedCalls) {
|
||||
// 1 second
|
||||
for (int i = 0; i < 50; i++) {
|
||||
for (int j = 0; j < numChannels; j++) {
|
||||
m_pdp->GetCurrent(j);
|
||||
m_pdp.GetCurrent(j);
|
||||
}
|
||||
m_pdp->GetVoltage();
|
||||
m_pdp.GetVoltage();
|
||||
}
|
||||
Wait(20_ms);
|
||||
frc::Wait(20_ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the current changes when the motor is driven using a talon
|
||||
*/
|
||||
TEST_F(PowerDistributionPanelTest, CheckCurrentTalon) {
|
||||
Wait(kMotorTime);
|
||||
frc::Wait(kMotorTime);
|
||||
|
||||
/* The Current should be 0 */
|
||||
EXPECT_FLOAT_EQ(0, m_pdp->GetCurrent(TestBench::kTalonPDPChannel))
|
||||
EXPECT_FLOAT_EQ(0, m_pdp.GetCurrent(TestBench::kTalonPDPChannel))
|
||||
<< "The Talon current was non-zero";
|
||||
|
||||
/* Set the motor to full forward */
|
||||
m_talon->Set(1.0);
|
||||
Wait(kMotorTime);
|
||||
m_talon.Set(1.0);
|
||||
frc::Wait(kMotorTime);
|
||||
|
||||
/* The current should now be positive */
|
||||
ASSERT_GT(m_pdp->GetCurrent(TestBench::kTalonPDPChannel), 0)
|
||||
ASSERT_GT(m_pdp.GetCurrent(TestBench::kTalonPDPChannel), 0)
|
||||
<< "The Talon current was not positive";
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#include "frc/Timer.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static const char* kFileName = "networktables.ini";
|
||||
static constexpr auto kSaveTime = 1.2_s;
|
||||
|
||||
@@ -26,6 +24,7 @@ static constexpr auto kSaveTime = 1.2_s;
|
||||
TEST(PreferencesTest, ReadPreferencesFromFile) {
|
||||
auto inst = nt::NetworkTableInstance::GetDefault();
|
||||
inst.StopServer();
|
||||
|
||||
std::remove(kFileName);
|
||||
std::ofstream preferencesFile(kFileName);
|
||||
preferencesFile << "[NetworkTables Storage 3.0]" << std::endl;
|
||||
@@ -43,16 +42,17 @@ TEST(PreferencesTest, ReadPreferencesFromFile) {
|
||||
<< "double \"/Preferences/testFileGetLong\"=1000000000000000000"
|
||||
<< std::endl;
|
||||
preferencesFile.close();
|
||||
|
||||
inst.StartServer();
|
||||
|
||||
Preferences* preferences = Preferences::GetInstance();
|
||||
auto& preferences = *frc::Preferences::GetInstance();
|
||||
EXPECT_EQ("Hello, preferences file",
|
||||
preferences->GetString("testFileGetString"));
|
||||
EXPECT_EQ(1, preferences->GetInt("testFileGetInt"));
|
||||
EXPECT_FLOAT_EQ(0.5, preferences->GetDouble("testFileGetDouble"));
|
||||
EXPECT_FLOAT_EQ(0.25f, preferences->GetFloat("testFileGetFloat"));
|
||||
EXPECT_TRUE(preferences->GetBoolean("testFileGetBoolean"));
|
||||
EXPECT_EQ(1000000000000000000ll, preferences->GetLong("testFileGetLong"));
|
||||
preferences.GetString("testFileGetString"));
|
||||
EXPECT_EQ(1, preferences.GetInt("testFileGetInt"));
|
||||
EXPECT_FLOAT_EQ(0.5, preferences.GetDouble("testFileGetDouble"));
|
||||
EXPECT_FLOAT_EQ(0.25f, preferences.GetFloat("testFileGetFloat"));
|
||||
EXPECT_TRUE(preferences.GetBoolean("testFileGetBoolean"));
|
||||
EXPECT_EQ(1000000000000000000ll, preferences.GetLong("testFileGetLong"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,24 +62,24 @@ TEST(PreferencesTest, ReadPreferencesFromFile) {
|
||||
TEST(PreferencesTest, WritePreferencesToFile) {
|
||||
auto inst = nt::NetworkTableInstance::GetDefault();
|
||||
inst.StartServer();
|
||||
Preferences* preferences = Preferences::GetInstance();
|
||||
preferences->Remove("testFileGetString");
|
||||
preferences->Remove("testFileGetInt");
|
||||
preferences->Remove("testFileGetDouble");
|
||||
preferences->Remove("testFileGetFloat");
|
||||
preferences->Remove("testFileGetBoolean");
|
||||
preferences->Remove("testFileGetLong");
|
||||
auto& preferences = *frc::Preferences::GetInstance();
|
||||
preferences.Remove("testFileGetString");
|
||||
preferences.Remove("testFileGetInt");
|
||||
preferences.Remove("testFileGetDouble");
|
||||
preferences.Remove("testFileGetFloat");
|
||||
preferences.Remove("testFileGetBoolean");
|
||||
preferences.Remove("testFileGetLong");
|
||||
|
||||
Wait(kSaveTime);
|
||||
frc::Wait(kSaveTime);
|
||||
|
||||
preferences->SetString("testFileSetString", "Hello, preferences file");
|
||||
preferences->SetInt("testFileSetInt", 1);
|
||||
preferences->SetDouble("testFileSetDouble", 0.5);
|
||||
preferences->SetFloat("testFileSetFloat", 0.25f);
|
||||
preferences->SetBoolean("testFileSetBoolean", true);
|
||||
preferences->SetLong("testFileSetLong", 1000000000000000000ll);
|
||||
preferences.SetString("testFileSetString", "Hello, preferences file");
|
||||
preferences.SetInt("testFileSetInt", 1);
|
||||
preferences.SetDouble("testFileSetDouble", 0.5);
|
||||
preferences.SetFloat("testFileSetFloat", 0.25f);
|
||||
preferences.SetBoolean("testFileSetBoolean", true);
|
||||
preferences.SetLong("testFileSetLong", 1000000000000000000ll);
|
||||
|
||||
Wait(kSaveTime);
|
||||
frc::Wait(kSaveTime);
|
||||
|
||||
static char const* kExpectedFileContents[] = {
|
||||
"[NetworkTables Storage 3.0]",
|
||||
|
||||
@@ -11,82 +11,62 @@
|
||||
#include "frc/Timer.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static constexpr auto kDelayTime = 10_ms;
|
||||
|
||||
class RelayTest : public testing::Test {
|
||||
protected:
|
||||
Relay* m_relay;
|
||||
DigitalInput* m_forward;
|
||||
DigitalInput* m_reverse;
|
||||
TEST(RelayTest, BothDirections) {
|
||||
frc::Relay relay{TestBench::kRelayChannel};
|
||||
frc::DigitalInput forward{TestBench::kFakeRelayForward};
|
||||
frc::DigitalInput reverse{TestBench::kFakeRelayReverse};
|
||||
|
||||
void SetUp() override {
|
||||
m_relay = new Relay(TestBench::kRelayChannel);
|
||||
m_forward = new DigitalInput(TestBench::kFakeRelayForward);
|
||||
m_reverse = new DigitalInput(TestBench::kFakeRelayReverse);
|
||||
}
|
||||
// Set the relay to forward
|
||||
relay.Set(frc::Relay::kForward);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_TRUE(forward.Get()) << "Relay did not set forward";
|
||||
EXPECT_FALSE(reverse.Get()) << "Relay did not set forward";
|
||||
EXPECT_EQ(relay.Get(), frc::Relay::kForward);
|
||||
|
||||
void TearDown() override {
|
||||
delete m_relay;
|
||||
delete m_forward;
|
||||
delete m_reverse;
|
||||
}
|
||||
// Set the relay to reverse
|
||||
relay.Set(frc::Relay::kReverse);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_TRUE(reverse.Get()) << "Relay did not set reverse";
|
||||
EXPECT_FALSE(forward.Get()) << "Relay did not set reverse";
|
||||
EXPECT_EQ(relay.Get(), frc::Relay::kReverse);
|
||||
|
||||
void Reset() { m_relay->Set(Relay::kOff); }
|
||||
};
|
||||
// Set the relay to off
|
||||
relay.Set(frc::Relay::kOff);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_FALSE(forward.Get()) << "Relay did not set off";
|
||||
EXPECT_FALSE(reverse.Get()) << "Relay did not set off";
|
||||
EXPECT_EQ(relay.Get(), frc::Relay::kOff);
|
||||
|
||||
/**
|
||||
* Test the relay by setting it forward, reverse, off, and on.
|
||||
*/
|
||||
TEST_F(RelayTest, Relay) {
|
||||
Reset();
|
||||
|
||||
// set the relay to forward
|
||||
m_relay->Set(Relay::kForward);
|
||||
Wait(kDelayTime);
|
||||
EXPECT_TRUE(m_forward->Get()) << "Relay did not set forward";
|
||||
EXPECT_FALSE(m_reverse->Get()) << "Relay did not set forward";
|
||||
EXPECT_EQ(m_relay->Get(), Relay::kForward);
|
||||
|
||||
// set the relay to reverse
|
||||
m_relay->Set(Relay::kReverse);
|
||||
Wait(kDelayTime);
|
||||
EXPECT_TRUE(m_reverse->Get()) << "Relay did not set reverse";
|
||||
EXPECT_FALSE(m_forward->Get()) << "Relay did not set reverse";
|
||||
EXPECT_EQ(m_relay->Get(), Relay::kReverse);
|
||||
|
||||
// set the relay to off
|
||||
m_relay->Set(Relay::kOff);
|
||||
Wait(kDelayTime);
|
||||
EXPECT_FALSE(m_forward->Get()) << "Relay did not set off";
|
||||
EXPECT_FALSE(m_reverse->Get()) << "Relay did not set off";
|
||||
EXPECT_EQ(m_relay->Get(), Relay::kOff);
|
||||
|
||||
// set the relay to on
|
||||
m_relay->Set(Relay::kOn);
|
||||
Wait(kDelayTime);
|
||||
EXPECT_TRUE(m_forward->Get()) << "Relay did not set on";
|
||||
EXPECT_TRUE(m_reverse->Get()) << "Relay did not set on";
|
||||
EXPECT_EQ(m_relay->Get(), Relay::kOn);
|
||||
|
||||
// test forward direction
|
||||
delete m_relay;
|
||||
m_relay = new Relay(TestBench::kRelayChannel, Relay::kForwardOnly);
|
||||
|
||||
m_relay->Set(Relay::kOn);
|
||||
Wait(kDelayTime);
|
||||
EXPECT_TRUE(m_forward->Get()) << "Relay did not set forward";
|
||||
EXPECT_FALSE(m_reverse->Get()) << "Relay did not set forward";
|
||||
EXPECT_EQ(m_relay->Get(), Relay::kOn);
|
||||
|
||||
// test reverse direction
|
||||
delete m_relay;
|
||||
m_relay = new Relay(TestBench::kRelayChannel, Relay::kReverseOnly);
|
||||
|
||||
m_relay->Set(Relay::kOn);
|
||||
Wait(kDelayTime);
|
||||
EXPECT_FALSE(m_forward->Get()) << "Relay did not set reverse";
|
||||
EXPECT_TRUE(m_reverse->Get()) << "Relay did not set reverse";
|
||||
EXPECT_EQ(m_relay->Get(), Relay::kOn);
|
||||
// Set the relay to on
|
||||
relay.Set(frc::Relay::kOn);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_TRUE(forward.Get()) << "Relay did not set on";
|
||||
EXPECT_TRUE(reverse.Get()) << "Relay did not set on";
|
||||
EXPECT_EQ(relay.Get(), frc::Relay::kOn);
|
||||
}
|
||||
|
||||
TEST(RelayTest, ForwardOnly) {
|
||||
frc::Relay relay{TestBench::kRelayChannel, frc::Relay::kForwardOnly};
|
||||
frc::DigitalInput forward{TestBench::kFakeRelayForward};
|
||||
frc::DigitalInput reverse{TestBench::kFakeRelayReverse};
|
||||
|
||||
relay.Set(frc::Relay::kOn);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_TRUE(forward.Get()) << "Relay did not set forward";
|
||||
EXPECT_FALSE(reverse.Get()) << "Relay did not set forward";
|
||||
EXPECT_EQ(relay.Get(), frc::Relay::kOn);
|
||||
}
|
||||
|
||||
TEST(RelayTest, ReverseOnly) {
|
||||
frc::Relay relay{TestBench::kRelayChannel, frc::Relay::kReverseOnly};
|
||||
frc::DigitalInput forward{TestBench::kFakeRelayForward};
|
||||
frc::DigitalInput reverse{TestBench::kFakeRelayReverse};
|
||||
|
||||
relay.Set(frc::Relay::kOn);
|
||||
frc::Wait(kDelayTime);
|
||||
EXPECT_FALSE(forward.Get()) << "Relay did not set reverse";
|
||||
EXPECT_TRUE(reverse.Get()) << "Relay did not set reverse";
|
||||
EXPECT_EQ(relay.Get(), frc::Relay::kOn);
|
||||
}
|
||||
|
||||
@@ -3,63 +3,63 @@
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <thread>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <hal/HAL.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "frc/DriverStation.h"
|
||||
#include "frc/Timer.h"
|
||||
#include "frc/livewindow/LiveWindow.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "mockds/MockDS.h"
|
||||
|
||||
using namespace frc;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
class TestEnvironment : public testing::Environment {
|
||||
bool m_alreadySetUp = false;
|
||||
MockDS m_mockDS;
|
||||
|
||||
public:
|
||||
void SetUp() override {
|
||||
/* Only set up once. This allows gtest_repeat to be used to
|
||||
automatically repeat tests. */
|
||||
TestEnvironment() {
|
||||
// Only set up once. This allows gtest_repeat to be used to automatically
|
||||
// repeat tests.
|
||||
if (m_alreadySetUp) {
|
||||
return;
|
||||
}
|
||||
m_alreadySetUp = true;
|
||||
|
||||
if (!HAL_Initialize(500, 0)) {
|
||||
wpi::errs() << "FATAL ERROR: HAL could not be initialized\n";
|
||||
fmt::print(stderr, "FATAL ERROR: HAL could not be initialized\n");
|
||||
std::exit(-1);
|
||||
}
|
||||
|
||||
m_mockDS.start();
|
||||
m_mockDS.Start();
|
||||
|
||||
/* This sets up the network communications library to enable the driver
|
||||
station. After starting network coms, it will loop until the driver
|
||||
station returns that the robot is enabled, to ensure that tests
|
||||
will be able to run on the hardware. */
|
||||
// This sets up the network communications library to enable the driver
|
||||
// station. After starting network coms, it will loop until the driver
|
||||
// station returns that the robot is enabled, to ensure that tests will be
|
||||
// able to run on the hardware.
|
||||
HAL_ObserveUserProgramStarting();
|
||||
LiveWindow::GetInstance()->SetEnabled(false);
|
||||
frc::LiveWindow::GetInstance()->SetEnabled(false);
|
||||
|
||||
wpi::outs() << "Started coms\n";
|
||||
fmt::print("Started coms\n");
|
||||
|
||||
int enableCounter = 0;
|
||||
while (!DriverStation::GetInstance().IsEnabled()) {
|
||||
while (!frc::DriverStation::GetInstance().IsEnabled()) {
|
||||
if (enableCounter > 50) {
|
||||
// Robot did not enable properly after 5 seconds.
|
||||
// Force exit
|
||||
wpi::errs() << " Failed to enable. Aborting\n";
|
||||
fmt::print(stderr, " Failed to enable. Aborting\n");
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
Wait(0.1_s);
|
||||
std::this_thread::sleep_for(100ms);
|
||||
|
||||
wpi::outs() << "Waiting for enable: " << enableCounter++ << "\n";
|
||||
fmt::print("Waiting for enable: {}\n", enableCounter++);
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override { m_mockDS.stop(); }
|
||||
~TestEnvironment() { m_mockDS.Stop(); }
|
||||
};
|
||||
|
||||
testing::Environment* const environment =
|
||||
|
||||
@@ -13,137 +13,79 @@
|
||||
#include "frc/Timer.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static constexpr auto kServoResetTime = 2_s;
|
||||
|
||||
static constexpr double kTestAngle = 90.0;
|
||||
|
||||
static constexpr double kTiltSetpoint0 = 0.22;
|
||||
static constexpr double kTiltSetpoint45 = 0.45;
|
||||
static constexpr double kTiltSetpoint90 = 0.68;
|
||||
static constexpr auto kTiltTime = 1_s;
|
||||
static constexpr double kAccelerometerTolerance = 0.2;
|
||||
static constexpr double kSensitivity = 0.013;
|
||||
|
||||
/**
|
||||
* A fixture for the camera with two servos and a gyro
|
||||
*/
|
||||
class TiltPanCameraTest : public testing::Test {
|
||||
protected:
|
||||
static AnalogGyro* m_gyro;
|
||||
Servo *m_tilt, *m_pan;
|
||||
Accelerometer* m_spiAccel;
|
||||
frc::Servo m_tilt{TestBench::kCameraTiltChannel};
|
||||
frc::Servo m_pan{TestBench::kCameraPanChannel};
|
||||
frc::ADXL345_SPI m_spiAccel{frc::SPI::kOnboardCS1};
|
||||
|
||||
static void SetUpTestCase() {
|
||||
// The gyro object blocks for 5 seconds in the constructor, so only
|
||||
// construct it once for the whole test case
|
||||
m_gyro = new AnalogGyro(TestBench::kCameraGyroChannel);
|
||||
m_gyro->SetSensitivity(kSensitivity);
|
||||
TiltPanCameraTest() {
|
||||
m_tilt.Set(kTiltSetpoint45);
|
||||
m_pan.SetAngle(0.0);
|
||||
|
||||
// Wait for servos to reset
|
||||
frc::Wait(2_s);
|
||||
}
|
||||
|
||||
static void TearDownTestCase() { delete m_gyro; }
|
||||
/**
|
||||
* Test if the servo turns 90 degrees and the gyroscope measures this angle
|
||||
* Note servo on TestBench is not the same type of servo that servo class
|
||||
* was designed for so setAngle is significantly off. This has been calibrated
|
||||
* for the servo on the rig.
|
||||
*/
|
||||
void GyroTests(frc::AnalogGyro& gyro) {
|
||||
gyro.SetSensitivity(0.013);
|
||||
|
||||
void SetUp() override {
|
||||
m_tilt = new Servo(TestBench::kCameraTiltChannel);
|
||||
m_pan = new Servo(TestBench::kCameraPanChannel);
|
||||
m_spiAccel = new ADXL345_SPI(SPI::kOnboardCS1);
|
||||
gyro.Reset();
|
||||
|
||||
m_tilt->Set(kTiltSetpoint45);
|
||||
m_pan->SetAngle(0.0);
|
||||
// Accumulator needs a small amount of time to reset before being tested
|
||||
frc::Wait(1_ms);
|
||||
|
||||
Wait(kServoResetTime);
|
||||
// Verify the gyro angle defaults to 0 immediately after being reset
|
||||
EXPECT_NEAR(0.0, gyro.GetAngle(), 1.0);
|
||||
|
||||
m_gyro->Reset();
|
||||
}
|
||||
// Make sure that the gyro doesn't get jerked when the servo goes to zero.
|
||||
m_pan.SetAngle(0.0);
|
||||
frc::Wait(0.5_s);
|
||||
gyro.Reset();
|
||||
|
||||
void DefaultGyroAngle();
|
||||
void GyroAngle();
|
||||
void GyroCalibratedParameters();
|
||||
for (int32_t i = 0; i < 600; i++) {
|
||||
m_pan.Set(i / 1000.0);
|
||||
frc::Wait(1_ms);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete m_tilt;
|
||||
delete m_pan;
|
||||
delete m_spiAccel;
|
||||
double gyroAngle = gyro.GetAngle();
|
||||
|
||||
EXPECT_NEAR(gyroAngle, 90.0, 10.0)
|
||||
<< "Gyro measured " << gyroAngle
|
||||
<< " degrees, servo should have turned 90 degrees";
|
||||
}
|
||||
};
|
||||
|
||||
AnalogGyro* TiltPanCameraTest::m_gyro = nullptr;
|
||||
TEST_F(TiltPanCameraTest, Gyro) {
|
||||
int cCenter;
|
||||
double cOffset;
|
||||
|
||||
/**
|
||||
* Test if the gyro angle defaults to 0 immediately after being reset.
|
||||
*/
|
||||
void TiltPanCameraTest::DefaultGyroAngle() {
|
||||
EXPECT_NEAR(0.0, m_gyro->GetAngle(), 1.0);
|
||||
}
|
||||
{
|
||||
frc::AnalogGyro gyro{TestBench::kCameraGyroChannel};
|
||||
GyroTests(gyro);
|
||||
|
||||
/**
|
||||
* Test if the servo turns 90 degrees and the gyroscope measures this angle
|
||||
* Note servo on TestBench is not the same type of servo that servo class
|
||||
* was designed for so setAngle is significantly off. This has been calibrated
|
||||
* for the servo on the rig.
|
||||
*/
|
||||
void TiltPanCameraTest::GyroAngle() {
|
||||
// Make sure that the gyro doesn't get jerked when the servo goes to zero.
|
||||
m_pan->SetAngle(0.0);
|
||||
Wait(0.5_s);
|
||||
m_gyro->Reset();
|
||||
|
||||
for (int32_t i = 0; i < 600; i++) {
|
||||
m_pan->Set(i / 1000.0);
|
||||
Wait(1_ms);
|
||||
// Gets calibrated parameters from previously calibrated gyro, allocates a
|
||||
// new gyro with the given parameters for center and offset, and re-runs
|
||||
// tests on the new gyro.
|
||||
cCenter = gyro.GetCenter();
|
||||
cOffset = gyro.GetOffset();
|
||||
}
|
||||
|
||||
double gyroAngle = m_gyro->GetAngle();
|
||||
|
||||
EXPECT_NEAR(gyroAngle, kTestAngle, 10.0)
|
||||
<< "Gyro measured " << gyroAngle << " degrees, servo should have turned "
|
||||
<< kTestAngle << " degrees";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets calibrated parameters from previously calibrated gyro, allocates a new
|
||||
* gyro with the given parameters for center and offset, and re-runs tests on
|
||||
* the new gyro.
|
||||
*/
|
||||
void TiltPanCameraTest::GyroCalibratedParameters() {
|
||||
uint32_t cCenter = m_gyro->GetCenter();
|
||||
double cOffset = m_gyro->GetOffset();
|
||||
delete m_gyro;
|
||||
m_gyro = new AnalogGyro(TestBench::kCameraGyroChannel, cCenter, cOffset);
|
||||
m_gyro->SetSensitivity(kSensitivity);
|
||||
|
||||
// Default gyro angle test
|
||||
// Accumulator needs a small amount of time to reset before being tested
|
||||
m_gyro->Reset();
|
||||
Wait(1_ms);
|
||||
EXPECT_NEAR(0.0, m_gyro->GetAngle(), 1.0);
|
||||
|
||||
// Gyro angle test
|
||||
// Make sure that the gyro doesn't get jerked when the servo goes to zero.
|
||||
m_pan->SetAngle(0.0);
|
||||
Wait(0.5_s);
|
||||
m_gyro->Reset();
|
||||
|
||||
for (int32_t i = 0; i < 600; i++) {
|
||||
m_pan->Set(i / 1000.0);
|
||||
Wait(1_ms);
|
||||
}
|
||||
|
||||
double gyroAngle = m_gyro->GetAngle();
|
||||
|
||||
EXPECT_NEAR(gyroAngle, kTestAngle, 10.0)
|
||||
<< "Gyro measured " << gyroAngle << " degrees, servo should have turned "
|
||||
<< kTestAngle << " degrees";
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all gyro tests in one function to make sure they are run in order.
|
||||
*/
|
||||
TEST_F(TiltPanCameraTest, TestAllGyroTests) {
|
||||
DefaultGyroAngle();
|
||||
GyroAngle();
|
||||
GyroCalibratedParameters();
|
||||
frc::AnalogGyro gyro{TestBench::kCameraGyroChannel, cCenter, cOffset};
|
||||
GyroTests(gyro);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,21 +93,24 @@ TEST_F(TiltPanCameraTest, TestAllGyroTests) {
|
||||
* camera rotates
|
||||
*/
|
||||
TEST_F(TiltPanCameraTest, SPIAccelerometer) {
|
||||
m_tilt->Set(kTiltSetpoint0);
|
||||
Wait(kTiltTime);
|
||||
EXPECT_NEAR(-1.0, m_spiAccel->GetX(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(0.0, m_spiAccel->GetY(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(0.0, m_spiAccel->GetZ(), kAccelerometerTolerance);
|
||||
static constexpr auto kTiltTime = 1_s;
|
||||
static constexpr double kAccelerometerTolerance = 0.2;
|
||||
|
||||
m_tilt->Set(kTiltSetpoint45);
|
||||
Wait(kTiltTime);
|
||||
EXPECT_NEAR(-std::sqrt(0.5), m_spiAccel->GetX(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(0.0, m_spiAccel->GetY(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(std::sqrt(0.5), m_spiAccel->GetZ(), kAccelerometerTolerance);
|
||||
m_tilt.Set(kTiltSetpoint0);
|
||||
frc::Wait(kTiltTime);
|
||||
EXPECT_NEAR(-1.0, m_spiAccel.GetX(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(0.0, m_spiAccel.GetY(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(0.0, m_spiAccel.GetZ(), kAccelerometerTolerance);
|
||||
|
||||
m_tilt->Set(kTiltSetpoint90);
|
||||
Wait(kTiltTime);
|
||||
EXPECT_NEAR(0.0, m_spiAccel->GetX(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(0.0, m_spiAccel->GetY(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(1.0, m_spiAccel->GetZ(), kAccelerometerTolerance);
|
||||
m_tilt.Set(kTiltSetpoint45);
|
||||
frc::Wait(kTiltTime);
|
||||
EXPECT_NEAR(-std::sqrt(0.5), m_spiAccel.GetX(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(0.0, m_spiAccel.GetY(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(std::sqrt(0.5), m_spiAccel.GetZ(), kAccelerometerTolerance);
|
||||
|
||||
m_tilt.Set(kTiltSetpoint90);
|
||||
frc::Wait(kTiltTime);
|
||||
EXPECT_NEAR(0.0, m_spiAccel.GetX(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(0.0, m_spiAccel.GetY(), kAccelerometerTolerance);
|
||||
EXPECT_NEAR(1.0, m_spiAccel.GetZ(), kAccelerometerTolerance);
|
||||
}
|
||||
|
||||
@@ -1,437 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "command/MockCommand.h"
|
||||
#include "frc/DriverStation.h"
|
||||
#include "frc/RobotState.h"
|
||||
#include "frc/Timer.h"
|
||||
#include "frc/commands/CommandGroup.h"
|
||||
#include "frc/commands/Scheduler.h"
|
||||
#include "frc/commands/Subsystem.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
class CommandTest : public testing::Test {
|
||||
protected:
|
||||
void SetUp() override { Scheduler::GetInstance()->SetEnabled(true); }
|
||||
|
||||
/**
|
||||
* Tears Down the Scheduler at the end of each test.
|
||||
* Must be called at the end of each test inside each test in order to prevent
|
||||
* them being deallocated
|
||||
* when they leave the scope of the test (causing a segfault).
|
||||
* This can not be done within the virtual void Teardown() method because it
|
||||
* is called outside of the
|
||||
* scope of the test.
|
||||
*/
|
||||
void TeardownScheduler() { Scheduler::GetInstance()->ResetAll(); }
|
||||
|
||||
void AssertCommandState(MockCommand* command, int32_t initialize,
|
||||
int32_t execute, int32_t isFinished, int32_t end,
|
||||
int32_t interrupted) {
|
||||
EXPECT_EQ(initialize, command->GetInitializeCount());
|
||||
EXPECT_EQ(execute, command->GetExecuteCount());
|
||||
EXPECT_EQ(isFinished, command->GetIsFinishedCount());
|
||||
EXPECT_EQ(end, command->GetEndCount());
|
||||
EXPECT_EQ(interrupted, command->GetInterruptedCount());
|
||||
}
|
||||
};
|
||||
|
||||
class ASubsystem : public Subsystem {
|
||||
private:
|
||||
Command* m_command = nullptr;
|
||||
|
||||
public:
|
||||
explicit ASubsystem(const std::string& name) : Subsystem(name) {}
|
||||
|
||||
void InitDefaultCommand() override {
|
||||
if (m_command != nullptr) {
|
||||
SetDefaultCommand(m_command);
|
||||
}
|
||||
}
|
||||
|
||||
void Init(Command* command) { m_command = command; }
|
||||
};
|
||||
|
||||
// CommandParallelGroupTest ported from CommandParallelGroupTest.java
|
||||
TEST_F(CommandTest, ParallelCommands) {
|
||||
auto command1 = new MockCommand;
|
||||
auto command2 = new MockCommand;
|
||||
CommandGroup commandGroup;
|
||||
|
||||
commandGroup.AddParallel(command1);
|
||||
commandGroup.AddParallel(command2);
|
||||
|
||||
AssertCommandState(command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(command2, 0, 0, 0, 0, 0);
|
||||
commandGroup.Start();
|
||||
AssertCommandState(command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(command2, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(command2, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(command2, 1, 1, 1, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(command2, 1, 2, 2, 0, 0);
|
||||
command1->SetHasFinished(true);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(command2, 1, 3, 3, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(command2, 1, 4, 4, 0, 0);
|
||||
command2->SetHasFinished(true);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(command2, 1, 5, 5, 1, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
// END CommandParallelGroupTest
|
||||
|
||||
// CommandScheduleTest ported from CommandScheduleTest.java
|
||||
TEST_F(CommandTest, RunAndTerminate) {
|
||||
MockCommand command;
|
||||
command.Start();
|
||||
AssertCommandState(&command, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 1, 1, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 2, 2, 0, 0);
|
||||
command.SetHasFinished(true);
|
||||
AssertCommandState(&command, 1, 2, 2, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 3, 3, 1, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 3, 3, 1, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(CommandTest, RunAndCancel) {
|
||||
MockCommand command;
|
||||
command.Start();
|
||||
AssertCommandState(&command, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 1, 1, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 2, 2, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 3, 3, 0, 0);
|
||||
command.Cancel();
|
||||
AssertCommandState(&command, 1, 3, 3, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 3, 3, 0, 1);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 3, 3, 0, 1);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
// END CommandScheduleTest
|
||||
|
||||
// CommandSequentialGroupTest ported from CommandSequentialGroupTest.java
|
||||
TEST_F(CommandTest, ThreeCommandOnSubSystem) {
|
||||
ASubsystem subsystem("Three Command Test Subsystem");
|
||||
auto command1 = new MockCommand;
|
||||
command1->Requires(&subsystem);
|
||||
auto command2 = new MockCommand;
|
||||
command2->Requires(&subsystem);
|
||||
auto command3 = new MockCommand;
|
||||
command3->Requires(&subsystem);
|
||||
|
||||
CommandGroup commandGroup;
|
||||
commandGroup.AddSequential(command1, 1_s);
|
||||
commandGroup.AddSequential(command2, 2_s);
|
||||
commandGroup.AddSequential(command3);
|
||||
|
||||
AssertCommandState(command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(command2, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(command3, 0, 0, 0, 0, 0);
|
||||
|
||||
commandGroup.Start();
|
||||
AssertCommandState(command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(command2, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(command3, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(command2, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(command3, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(command2, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(command3, 0, 0, 0, 0, 0);
|
||||
Wait(1_s);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 1, 1, 0, 1);
|
||||
AssertCommandState(command2, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(command3, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 1, 1, 0, 1);
|
||||
AssertCommandState(command2, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(command3, 0, 0, 0, 0, 0);
|
||||
Wait(2_s);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 1, 1, 0, 1);
|
||||
AssertCommandState(command2, 1, 2, 2, 0, 1);
|
||||
AssertCommandState(command3, 1, 1, 1, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 1, 1, 0, 1);
|
||||
AssertCommandState(command2, 1, 2, 2, 0, 1);
|
||||
AssertCommandState(command3, 1, 2, 2, 0, 0);
|
||||
command3->SetHasFinished(true);
|
||||
AssertCommandState(command1, 1, 1, 1, 0, 1);
|
||||
AssertCommandState(command2, 1, 2, 2, 0, 1);
|
||||
AssertCommandState(command3, 1, 2, 2, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 1, 1, 0, 1);
|
||||
AssertCommandState(command2, 1, 2, 2, 0, 1);
|
||||
AssertCommandState(command3, 1, 3, 3, 1, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(command1, 1, 1, 1, 0, 1);
|
||||
AssertCommandState(command2, 1, 2, 2, 0, 1);
|
||||
AssertCommandState(command3, 1, 3, 3, 1, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
// END CommandSequentialGroupTest
|
||||
|
||||
// CommandSequentialGroupTest ported from CommandSequentialGroupTest.java
|
||||
TEST_F(CommandTest, OneCommandSupersedingAnotherBecauseOfDependencies) {
|
||||
ASubsystem subsystem("Command Superseding Test Subsystem");
|
||||
MockCommand command1;
|
||||
command1.Requires(&subsystem);
|
||||
MockCommand command2;
|
||||
command2.Requires(&subsystem);
|
||||
|
||||
AssertCommandState(&command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
command1.Start();
|
||||
AssertCommandState(&command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 3, 3, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
command2.Start();
|
||||
AssertCommandState(&command1, 1, 3, 3, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 4, 4, 0, 1);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 4, 4, 0, 1);
|
||||
AssertCommandState(&command2, 1, 1, 1, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 4, 4, 0, 1);
|
||||
AssertCommandState(&command2, 1, 2, 2, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 4, 4, 0, 1);
|
||||
AssertCommandState(&command2, 1, 3, 3, 0, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(CommandTest,
|
||||
OneCommandFailingSupersedingBecauseFirstCanNotBeInterrupted) {
|
||||
ASubsystem subsystem("Command Superseding Test Subsystem");
|
||||
MockCommand command1;
|
||||
|
||||
command1.Requires(&subsystem);
|
||||
|
||||
command1.SetInterruptible(false);
|
||||
MockCommand command2;
|
||||
command2.Requires(&subsystem);
|
||||
|
||||
AssertCommandState(&command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
command1.Start();
|
||||
AssertCommandState(&command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 3, 3, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
command2.Start();
|
||||
AssertCommandState(&command1, 1, 3, 3, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command1, 1, 4, 4, 0, 0);
|
||||
AssertCommandState(&command2, 0, 0, 0, 0, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
// END CommandSequentialGroupTest
|
||||
|
||||
class ModifiedMockCommand : public MockCommand {
|
||||
public:
|
||||
ModifiedMockCommand() : MockCommand() { SetTimeout(2_s); }
|
||||
bool IsFinished() override {
|
||||
return MockCommand::IsFinished() || IsTimedOut();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CommandTest, TwoSecondTimeout) {
|
||||
ASubsystem subsystem("Two Second Timeout Test Subsystem");
|
||||
ModifiedMockCommand command;
|
||||
command.Requires(&subsystem);
|
||||
|
||||
command.Start();
|
||||
AssertCommandState(&command, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 1, 1, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 2, 2, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 3, 3, 0, 0);
|
||||
Wait(2_s);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 4, 4, 1, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(&command, 1, 4, 4, 1, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(CommandTest, DefaultCommandWhereTheInteruptingCommandEndsItself) {
|
||||
ASubsystem subsystem("Default Command Test Subsystem");
|
||||
auto defaultCommand = new MockCommand;
|
||||
defaultCommand->Requires(&subsystem);
|
||||
MockCommand anotherCommand;
|
||||
anotherCommand.Requires(&subsystem);
|
||||
|
||||
AssertCommandState(defaultCommand, 0, 0, 0, 0, 0);
|
||||
subsystem.Init(defaultCommand);
|
||||
|
||||
AssertCommandState(defaultCommand, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 1, 1, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 2, 2, 0, 0);
|
||||
|
||||
anotherCommand.Start();
|
||||
AssertCommandState(defaultCommand, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(&anotherCommand, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 1, 1, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 2, 2, 0, 0);
|
||||
anotherCommand.SetHasFinished(true);
|
||||
AssertCommandState(defaultCommand, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 2, 2, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 3, 3, 1, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 2, 4, 4, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 3, 3, 1, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 2, 5, 5, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 3, 3, 1, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(CommandTest, DefaultCommandsInterruptingCommandCanceled) {
|
||||
ASubsystem subsystem("Default Command Test Subsystem");
|
||||
auto defaultCommand = new MockCommand;
|
||||
defaultCommand->Requires(&subsystem);
|
||||
MockCommand anotherCommand;
|
||||
anotherCommand.Requires(&subsystem);
|
||||
|
||||
AssertCommandState(defaultCommand, 0, 0, 0, 0, 0);
|
||||
subsystem.Init(defaultCommand);
|
||||
AssertCommandState(defaultCommand, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 1, 1, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 2, 2, 0, 0);
|
||||
|
||||
anotherCommand.Start();
|
||||
AssertCommandState(defaultCommand, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(&anotherCommand, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 0, 0, 0, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 1, 1, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 2, 2, 0, 0);
|
||||
anotherCommand.Cancel();
|
||||
AssertCommandState(defaultCommand, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 2, 2, 0, 0);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 2, 2, 0, 1);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 2, 4, 4, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 2, 2, 0, 1);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(defaultCommand, 2, 5, 5, 0, 1);
|
||||
AssertCommandState(&anotherCommand, 1, 2, 2, 0, 1);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
@@ -1,432 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "command/MockCommand.h"
|
||||
#include "command/MockConditionalCommand.h"
|
||||
#include "frc/DriverStation.h"
|
||||
#include "frc/RobotState.h"
|
||||
#include "frc/commands/ConditionalCommand.h"
|
||||
#include "frc/commands/Scheduler.h"
|
||||
#include "frc/commands/Subsystem.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
class ConditionalCommandTest : public testing::Test {
|
||||
public:
|
||||
MockConditionalCommand* m_command;
|
||||
MockCommand* m_onTrue;
|
||||
MockCommand* m_onFalse;
|
||||
MockConditionalCommand* m_commandNull;
|
||||
Subsystem* m_subsystem;
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
Scheduler::GetInstance()->SetEnabled(true);
|
||||
|
||||
m_subsystem = new Subsystem("MockSubsystem");
|
||||
m_onTrue = new MockCommand(m_subsystem);
|
||||
m_onFalse = new MockCommand(m_subsystem);
|
||||
m_command = new MockConditionalCommand(m_onTrue, m_onFalse);
|
||||
m_commandNull = new MockConditionalCommand(m_onTrue, nullptr);
|
||||
}
|
||||
|
||||
void TearDown() override { delete m_command; }
|
||||
|
||||
/**
|
||||
* Tears Down the Scheduler at the end of each test.
|
||||
*
|
||||
* Must be called at the end of each test inside each test in order to prevent
|
||||
* them being deallocated when they leave the scope of the test (causing a
|
||||
* segfault). This cannot be done within the virtual void Teardown() method
|
||||
* because it is called outside of the scope of the test.
|
||||
*/
|
||||
void TeardownScheduler() { Scheduler::GetInstance()->ResetAll(); }
|
||||
|
||||
void AssertCommandState(MockCommand& command, int32_t initialize,
|
||||
int32_t execute, int32_t isFinished, int32_t end,
|
||||
int32_t interrupted) {
|
||||
EXPECT_EQ(initialize, command.GetInitializeCount());
|
||||
EXPECT_EQ(execute, command.GetExecuteCount());
|
||||
EXPECT_EQ(isFinished, command.GetIsFinishedCount());
|
||||
EXPECT_EQ(end, command.GetEndCount());
|
||||
EXPECT_EQ(interrupted, command.GetInterruptedCount());
|
||||
}
|
||||
|
||||
void AssertConditionalCommandState(MockConditionalCommand& command,
|
||||
int32_t initialize, int32_t execute,
|
||||
int32_t isFinished, int32_t end,
|
||||
int32_t interrupted) {
|
||||
EXPECT_EQ(initialize, command.GetInitializeCount());
|
||||
EXPECT_EQ(execute, command.GetExecuteCount());
|
||||
EXPECT_EQ(isFinished, command.GetIsFinishedCount());
|
||||
EXPECT_EQ(end, command.GetEndCount());
|
||||
EXPECT_EQ(interrupted, command.GetInterruptedCount());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ConditionalCommandTest, OnTrueTest) {
|
||||
m_command->SetCondition(true);
|
||||
|
||||
SCOPED_TRACE("1");
|
||||
Scheduler::GetInstance()->AddCommand(m_command);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("2");
|
||||
Scheduler::GetInstance()->Run(); // init command and select m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("3");
|
||||
Scheduler::GetInstance()->Run(); // init m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 1, 1, 0, 0);
|
||||
SCOPED_TRACE("4");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 2, 2, 0, 0);
|
||||
SCOPED_TRACE("5");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 3, 3, 0, 0);
|
||||
SCOPED_TRACE("6");
|
||||
m_onTrue->SetHasFinished(true);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 1, 0);
|
||||
SCOPED_TRACE("7");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 1, 0);
|
||||
|
||||
EXPECT_TRUE(m_onTrue->GetInitializeCount() > 0)
|
||||
<< "Did not initialize the true command\n";
|
||||
EXPECT_TRUE(m_onFalse->GetInitializeCount() == 0)
|
||||
<< "Initialized the false command\n";
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(ConditionalCommandTest, OnFalseTest) {
|
||||
m_command->SetCondition(false);
|
||||
|
||||
SCOPED_TRACE("1");
|
||||
Scheduler::GetInstance()->AddCommand(m_command);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("2");
|
||||
Scheduler::GetInstance()->Run(); // init command and select m_onTrue
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("3");
|
||||
Scheduler::GetInstance()->Run(); // init m_onTrue
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 1, 1, 0, 0);
|
||||
SCOPED_TRACE("4");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onFalse, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 2, 2, 0, 0);
|
||||
SCOPED_TRACE("5");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onFalse, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 3, 3, 0, 0);
|
||||
SCOPED_TRACE("6");
|
||||
m_onFalse->SetHasFinished(true);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onFalse, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 1, 0);
|
||||
SCOPED_TRACE("7");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onFalse, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 1, 0);
|
||||
|
||||
EXPECT_TRUE(m_onFalse->GetInitializeCount() > 0)
|
||||
<< "Did not initialize the false command";
|
||||
EXPECT_TRUE(m_onTrue->GetInitializeCount() == 0)
|
||||
<< "Initialized the true command";
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(ConditionalCommandTest, CancelSubCommandTest) {
|
||||
m_command->SetCondition(true);
|
||||
|
||||
SCOPED_TRACE("1");
|
||||
Scheduler::GetInstance()->AddCommand(m_command);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("2");
|
||||
Scheduler::GetInstance()->Run(); // init command and select m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("3");
|
||||
Scheduler::GetInstance()->Run(); // init m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 1, 1, 0, 0);
|
||||
SCOPED_TRACE("4");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 2, 2, 0, 0);
|
||||
SCOPED_TRACE("5");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 3, 3, 0, 0);
|
||||
SCOPED_TRACE("6");
|
||||
m_onTrue->Cancel();
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 2, 2, 0, 1);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 1, 0);
|
||||
SCOPED_TRACE("7");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 2, 2, 0, 1);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 1, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(ConditionalCommandTest, CancelCondCommandTest) {
|
||||
m_command->SetCondition(true);
|
||||
|
||||
SCOPED_TRACE("1");
|
||||
Scheduler::GetInstance()->AddCommand(m_command);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("2");
|
||||
Scheduler::GetInstance()->Run(); // init command and select m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("3");
|
||||
Scheduler::GetInstance()->Run(); // init m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 1, 1, 0, 0);
|
||||
SCOPED_TRACE("4");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 2, 2, 0, 0);
|
||||
SCOPED_TRACE("5");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 3, 3, 0, 0);
|
||||
SCOPED_TRACE("6");
|
||||
m_command->Cancel();
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 2, 2, 0, 1);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 3, 3, 0, 1);
|
||||
SCOPED_TRACE("7");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 2, 2, 0, 1);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 3, 3, 0, 1);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(ConditionalCommandTest, OnTrueTwiceTest) {
|
||||
m_command->SetCondition(true);
|
||||
|
||||
SCOPED_TRACE("1");
|
||||
Scheduler::GetInstance()->AddCommand(m_command);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("2");
|
||||
Scheduler::GetInstance()->Run(); // init command and select m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("3");
|
||||
Scheduler::GetInstance()->Run(); // init m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 1, 1, 0, 0);
|
||||
SCOPED_TRACE("4");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 2, 2, 0, 0);
|
||||
SCOPED_TRACE("5");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 3, 3, 0, 0);
|
||||
SCOPED_TRACE("6");
|
||||
m_onTrue->SetHasFinished(true);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 1, 0);
|
||||
SCOPED_TRACE("7");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 1, 0);
|
||||
|
||||
m_onTrue->ResetCounters();
|
||||
m_command->ResetCounters();
|
||||
Scheduler::GetInstance()->AddCommand(m_command);
|
||||
|
||||
SCOPED_TRACE("11");
|
||||
Scheduler::GetInstance()->AddCommand(m_command);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("12");
|
||||
Scheduler::GetInstance()->Run(); // init command and select m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("13");
|
||||
Scheduler::GetInstance()->Run(); // init m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 1, 1, 0, 0);
|
||||
SCOPED_TRACE("14");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 2, 2, 0, 0);
|
||||
SCOPED_TRACE("15");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 3, 3, 0, 0);
|
||||
SCOPED_TRACE("16");
|
||||
m_onTrue->SetHasFinished(true);
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 1, 0);
|
||||
SCOPED_TRACE("17");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 3, 3, 1, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 1, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(ConditionalCommandTest, OnTrueInstantTest) {
|
||||
m_command->SetCondition(true);
|
||||
m_onTrue->SetHasFinished(true);
|
||||
|
||||
SCOPED_TRACE("1");
|
||||
Scheduler::GetInstance()->AddCommand(m_command);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("2");
|
||||
Scheduler::GetInstance()->Run(); // init command and select m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("3");
|
||||
Scheduler::GetInstance()->Run(); // init m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 1, 1, 0, 0);
|
||||
SCOPED_TRACE("4");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 1, 1, 1, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 2, 2, 1, 0);
|
||||
SCOPED_TRACE("5");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 1, 1, 1, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 2, 2, 1, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(ConditionalCommandTest, CancelRequiresTest) {
|
||||
m_command->SetCondition(true);
|
||||
|
||||
SCOPED_TRACE("1");
|
||||
Scheduler::GetInstance()->AddCommand(m_command);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("2");
|
||||
Scheduler::GetInstance()->Run(); // init command and select m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("3");
|
||||
Scheduler::GetInstance()->Run(); // init m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 1, 1, 0, 0);
|
||||
SCOPED_TRACE("4");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 1, 1, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 2, 2, 0, 0);
|
||||
SCOPED_TRACE("5");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 2, 2, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 3, 3, 0, 0);
|
||||
SCOPED_TRACE("6");
|
||||
m_onFalse->Start();
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 3, 3, 0, 0);
|
||||
AssertCommandState(*m_onFalse, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 0, 1);
|
||||
SCOPED_TRACE("7");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 1, 3, 3, 0, 1);
|
||||
AssertCommandState(*m_onFalse, 1, 1, 1, 0, 0);
|
||||
AssertConditionalCommandState(*m_command, 1, 4, 4, 0, 1);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
|
||||
TEST_F(ConditionalCommandTest, OnFalseNullTest) {
|
||||
m_command->SetCondition(false);
|
||||
|
||||
SCOPED_TRACE("1");
|
||||
Scheduler::GetInstance()->AddCommand(m_commandNull);
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_commandNull, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("2");
|
||||
Scheduler::GetInstance()->Run(); // init command and select m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_commandNull, 0, 0, 0, 0, 0);
|
||||
SCOPED_TRACE("3");
|
||||
Scheduler::GetInstance()->Run(); // init m_onTrue
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_commandNull, 1, 1, 1, 1, 0);
|
||||
SCOPED_TRACE("4");
|
||||
Scheduler::GetInstance()->Run();
|
||||
AssertCommandState(*m_onTrue, 0, 0, 0, 0, 0);
|
||||
AssertConditionalCommandState(*m_commandNull, 1, 1, 1, 1, 0);
|
||||
|
||||
TeardownScheduler();
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "command/MockCommand.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
MockCommand::MockCommand(Subsystem* subsys) : MockCommand() {
|
||||
Requires(subsys);
|
||||
}
|
||||
|
||||
MockCommand::MockCommand() {
|
||||
m_initializeCount = 0;
|
||||
m_executeCount = 0;
|
||||
m_isFinishedCount = 0;
|
||||
m_hasFinished = false;
|
||||
m_endCount = 0;
|
||||
m_interruptedCount = 0;
|
||||
}
|
||||
|
||||
bool MockCommand::HasInitialized() {
|
||||
return GetInitializeCount() > 0;
|
||||
}
|
||||
|
||||
bool MockCommand::HasEnd() {
|
||||
return GetEndCount() > 0;
|
||||
}
|
||||
|
||||
bool MockCommand::HasInterrupted() {
|
||||
return GetInterruptedCount() > 0;
|
||||
}
|
||||
|
||||
void MockCommand::Initialize() {
|
||||
++m_initializeCount;
|
||||
}
|
||||
|
||||
void MockCommand::Execute() {
|
||||
++m_executeCount;
|
||||
}
|
||||
|
||||
bool MockCommand::IsFinished() {
|
||||
++m_isFinishedCount;
|
||||
return IsHasFinished();
|
||||
}
|
||||
|
||||
void MockCommand::End() {
|
||||
++m_endCount;
|
||||
}
|
||||
|
||||
void MockCommand::Interrupted() {
|
||||
++m_interruptedCount;
|
||||
}
|
||||
|
||||
void MockCommand::ResetCounters() {
|
||||
m_initializeCount = 0;
|
||||
m_executeCount = 0;
|
||||
m_isFinishedCount = 0;
|
||||
m_hasFinished = false;
|
||||
m_endCount = 0;
|
||||
m_interruptedCount = 0;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "command/MockConditionalCommand.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
MockConditionalCommand::MockConditionalCommand(MockCommand* onTrue,
|
||||
MockCommand* onFalse)
|
||||
: ConditionalCommand(onTrue, onFalse) {
|
||||
m_initializeCount = 0;
|
||||
m_executeCount = 0;
|
||||
m_isFinishedCount = 0;
|
||||
m_endCount = 0;
|
||||
m_interruptedCount = 0;
|
||||
}
|
||||
|
||||
void MockConditionalCommand::SetCondition(bool condition) {
|
||||
m_condition = condition;
|
||||
}
|
||||
|
||||
bool MockConditionalCommand::Condition() {
|
||||
return m_condition;
|
||||
}
|
||||
|
||||
bool MockConditionalCommand::HasInitialized() {
|
||||
return GetInitializeCount() > 0;
|
||||
}
|
||||
|
||||
bool MockConditionalCommand::HasEnd() {
|
||||
return GetEndCount() > 0;
|
||||
}
|
||||
|
||||
bool MockConditionalCommand::HasInterrupted() {
|
||||
return GetInterruptedCount() > 0;
|
||||
}
|
||||
|
||||
void MockConditionalCommand::Initialize() {
|
||||
++m_initializeCount;
|
||||
}
|
||||
|
||||
void MockConditionalCommand::Execute() {
|
||||
++m_executeCount;
|
||||
}
|
||||
|
||||
bool MockConditionalCommand::IsFinished() {
|
||||
++m_isFinishedCount;
|
||||
return ConditionalCommand::IsFinished();
|
||||
}
|
||||
|
||||
void MockConditionalCommand::End() {
|
||||
++m_endCount;
|
||||
}
|
||||
|
||||
void MockConditionalCommand::Interrupted() {
|
||||
++m_interruptedCount;
|
||||
}
|
||||
|
||||
void MockConditionalCommand::ResetCounters() {
|
||||
m_initializeCount = 0;
|
||||
m_executeCount = 0;
|
||||
m_isFinishedCount = 0;
|
||||
m_endCount = 0;
|
||||
m_interruptedCount = 0;
|
||||
}
|
||||
@@ -6,35 +6,32 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <hal/cpp/fpga_clock.h>
|
||||
#include <wpi/Logger.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/UDPClient.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
static void LoggerFunc(unsigned int level, const char* file, unsigned int line,
|
||||
const char* msg) {
|
||||
wpi::SmallString<128> buf;
|
||||
wpi::raw_svector_ostream oss(buf);
|
||||
if (level == 20) {
|
||||
oss << "DS: " << msg << '\n';
|
||||
wpi::errs() << oss.str();
|
||||
fmt::print(stderr, "DS: {}\n", msg);
|
||||
return;
|
||||
}
|
||||
|
||||
wpi::StringRef levelmsg;
|
||||
std::string_view levelmsg;
|
||||
if (level >= 50) {
|
||||
levelmsg = "CRITICAL: ";
|
||||
levelmsg = "CRITICAL";
|
||||
} else if (level >= 40) {
|
||||
levelmsg = "ERROR: ";
|
||||
levelmsg = "ERROR";
|
||||
} else if (level >= 30) {
|
||||
levelmsg = "WARNING: ";
|
||||
levelmsg = "WARNING";
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
oss << "DS: " << levelmsg << msg << " (" << file << ':' << line << ")\n";
|
||||
wpi::errs() << oss.str();
|
||||
fmt::print(stderr, "DS: {}: {} ({}:{})\n", levelmsg, msg, file, line);
|
||||
}
|
||||
|
||||
static void generateEnabledDsPacket(wpi::SmallVectorImpl<uint8_t>& data,
|
||||
@@ -48,9 +45,7 @@ static void generateEnabledDsPacket(wpi::SmallVectorImpl<uint8_t>& data,
|
||||
data.push_back(0x00); // red 1 station
|
||||
}
|
||||
|
||||
using namespace frc;
|
||||
|
||||
void MockDS::start() {
|
||||
void MockDS::Start() {
|
||||
if (m_active) {
|
||||
return;
|
||||
}
|
||||
@@ -83,7 +78,7 @@ void MockDS::start() {
|
||||
});
|
||||
}
|
||||
|
||||
void MockDS::stop() {
|
||||
void MockDS::Stop() {
|
||||
m_active = false;
|
||||
if (m_thread.joinable()) {
|
||||
m_thread.join();
|
||||
|
||||
@@ -7,19 +7,17 @@
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
namespace frc {
|
||||
class MockDS {
|
||||
public:
|
||||
MockDS() = default;
|
||||
~MockDS() { stop(); }
|
||||
~MockDS() { Stop(); }
|
||||
MockDS(const MockDS& other) = delete;
|
||||
MockDS& operator=(const MockDS& other) = delete;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void Start();
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
std::thread m_thread;
|
||||
std::atomic_bool m_active{false};
|
||||
};
|
||||
} // namespace frc
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "shuffleboard/MockActuatorSendable.h"
|
||||
|
||||
#include "frc/smartdashboard/SendableRegistry.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
MockActuatorSendable::MockActuatorSendable(wpi::StringRef name) {
|
||||
SendableRegistry::GetInstance().Add(this, name);
|
||||
}
|
||||
|
||||
void MockActuatorSendable::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetActuator(true);
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "frc/shuffleboard/ShuffleboardInstance.h" // NOLINT(build/include_order)
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <networktables/NetworkTableEntry.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
|
||||
#include "frc/shuffleboard/ShuffleboardInstance.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "shuffleboard/MockActuatorSendable.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
class ShuffleboardInstanceTest : public testing::Test {
|
||||
void SetUp() override {
|
||||
m_ntInstance = nt::NetworkTableInstance::Create();
|
||||
m_shuffleboardInstance =
|
||||
std::make_unique<detail::ShuffleboardInstance>(m_ntInstance);
|
||||
}
|
||||
|
||||
protected:
|
||||
nt::NetworkTableInstance m_ntInstance;
|
||||
std::unique_ptr<detail::ShuffleboardInstance> m_shuffleboardInstance;
|
||||
};
|
||||
|
||||
TEST_F(ShuffleboardInstanceTest, PathFluent) {
|
||||
auto entry = m_shuffleboardInstance->GetTab("Tab Title")
|
||||
.GetLayout("List", "List Layout")
|
||||
.Add("Data", "string")
|
||||
.WithWidget("Text View")
|
||||
.GetEntry();
|
||||
|
||||
EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
|
||||
EXPECT_EQ("/Shuffleboard/Tab Title/List/Data", entry.GetName())
|
||||
<< "Entry path generated incorrectly";
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardInstanceTest, NestedLayoutsFluent) {
|
||||
auto entry = m_shuffleboardInstance->GetTab("Tab")
|
||||
.GetLayout("First", "List")
|
||||
.GetLayout("Second", "List")
|
||||
.GetLayout("Third", "List")
|
||||
.GetLayout("Fourth", "List")
|
||||
.Add("Value", "string")
|
||||
.GetEntry();
|
||||
|
||||
EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
|
||||
EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value",
|
||||
entry.GetName())
|
||||
<< "Entry path generated incorrectly";
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardInstanceTest, NestedLayoutsOop) {
|
||||
ShuffleboardTab& tab = m_shuffleboardInstance->GetTab("Tab");
|
||||
ShuffleboardLayout& first = tab.GetLayout("First", "List");
|
||||
ShuffleboardLayout& second = first.GetLayout("Second", "List");
|
||||
ShuffleboardLayout& third = second.GetLayout("Third", "List");
|
||||
ShuffleboardLayout& fourth = third.GetLayout("Fourth", "List");
|
||||
SimpleWidget& widget = fourth.Add("Value", "string");
|
||||
auto entry = widget.GetEntry();
|
||||
|
||||
EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
|
||||
EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value",
|
||||
entry.GetName())
|
||||
<< "Entry path generated incorrectly";
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardInstanceTest, LayoutTypeIsSet) {
|
||||
std::string layoutType = "Type";
|
||||
m_shuffleboardInstance->GetTab("Tab").GetLayout("Title", layoutType);
|
||||
m_shuffleboardInstance->Update();
|
||||
nt::NetworkTableEntry entry = m_ntInstance.GetEntry(
|
||||
"/Shuffleboard/.metadata/Tab/Title/PreferredComponent");
|
||||
EXPECT_EQ(layoutType, entry.GetString("Not Set")) << "Layout type not set";
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardInstanceTest, NestedActuatorWidgetsAreDisabled) {
|
||||
MockActuatorSendable sendable("Actuator");
|
||||
m_shuffleboardInstance->GetTab("Tab")
|
||||
.GetLayout("Title", "Layout")
|
||||
.Add(sendable);
|
||||
auto controllableEntry =
|
||||
m_ntInstance.GetEntry("/Shuffleboard/Tab/Title/Actuator/.controllable");
|
||||
m_shuffleboardInstance->Update();
|
||||
|
||||
// Note: we use the unsafe `GetBoolean()` method because if the value is NOT
|
||||
// a boolean, or if it is not present, then something has clearly gone very,
|
||||
// very wrong
|
||||
bool controllable = controllableEntry.GetValue()->GetBoolean();
|
||||
// Sanity check
|
||||
EXPECT_TRUE(controllable)
|
||||
<< "The nested actuator widget should be enabled by default";
|
||||
m_shuffleboardInstance->DisableActuatorWidgets();
|
||||
controllable = controllableEntry.GetValue()->GetBoolean();
|
||||
EXPECT_FALSE(controllable)
|
||||
<< "The nested actuator widget should have been disabled";
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <networktables/NetworkTableEntry.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
|
||||
#include "frc/commands/InstantCommand.h"
|
||||
#include "frc/shuffleboard/ShuffleboardInstance.h"
|
||||
#include "frc/shuffleboard/ShuffleboardTab.h"
|
||||
#include "frc/smartdashboard/Sendable.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
class ShuffleboardTabTest : public testing::Test {
|
||||
void SetUp() override {
|
||||
m_ntInstance = nt::NetworkTableInstance::Create();
|
||||
m_instance = std::make_unique<detail::ShuffleboardInstance>(m_ntInstance);
|
||||
m_tab = &(m_instance->GetTab("Tab"));
|
||||
}
|
||||
|
||||
protected:
|
||||
nt::NetworkTableInstance m_ntInstance;
|
||||
ShuffleboardTab* m_tab;
|
||||
std::unique_ptr<detail::ShuffleboardInstance> m_instance;
|
||||
};
|
||||
|
||||
TEST_F(ShuffleboardTabTest, AddDouble) {
|
||||
auto entry = m_tab->Add("Double", 1.0).GetEntry();
|
||||
EXPECT_EQ("/Shuffleboard/Tab/Double", entry.GetName());
|
||||
EXPECT_FLOAT_EQ(1.0, entry.GetValue()->GetDouble());
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardTabTest, AddInteger) {
|
||||
auto entry = m_tab->Add("Int", 1).GetEntry();
|
||||
EXPECT_EQ("/Shuffleboard/Tab/Int", entry.GetName());
|
||||
EXPECT_FLOAT_EQ(1.0, entry.GetValue()->GetDouble());
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardTabTest, AddBoolean) {
|
||||
auto entry = m_tab->Add("Bool", false).GetEntry();
|
||||
EXPECT_EQ("/Shuffleboard/Tab/Bool", entry.GetName());
|
||||
EXPECT_FALSE(entry.GetValue()->GetBoolean());
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardTabTest, AddString) {
|
||||
auto entry = m_tab->Add("String", "foobar").GetEntry();
|
||||
EXPECT_EQ("/Shuffleboard/Tab/String", entry.GetName());
|
||||
EXPECT_EQ("foobar", entry.GetValue()->GetString());
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardTabTest, AddNamedSendableWithProperties) {
|
||||
InstantCommand sendable("Command");
|
||||
std::string widgetType = "Command Widget";
|
||||
wpi::StringMap<std::shared_ptr<nt::Value>> map;
|
||||
map.try_emplace("foo", nt::Value::MakeDouble(1234));
|
||||
map.try_emplace("bar", nt::Value::MakeString("baz"));
|
||||
m_tab->Add(sendable).WithWidget(widgetType).WithProperties(map);
|
||||
|
||||
m_instance->Update();
|
||||
std::string meta = "/Shuffleboard/.metadata/Tab/Command";
|
||||
|
||||
EXPECT_EQ(1234, m_ntInstance.GetEntry(meta + "/Properties/foo").GetDouble(-1))
|
||||
<< "Property 'foo' not set correctly";
|
||||
EXPECT_EQ("baz",
|
||||
m_ntInstance.GetEntry(meta + "/Properties/bar").GetString(""))
|
||||
<< "Property 'bar' not set correctly";
|
||||
EXPECT_EQ(widgetType,
|
||||
m_ntInstance.GetEntry(meta + "/PreferredComponent").GetString(""))
|
||||
<< "Preferred component not set correctly";
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardTabTest, AddNumberArray) {
|
||||
std::array<double, 3> expect = {{1.0, 2.0, 3.0}};
|
||||
auto entry = m_tab->Add("DoubleArray", expect).GetEntry();
|
||||
EXPECT_EQ("/Shuffleboard/Tab/DoubleArray", entry.GetName());
|
||||
|
||||
auto actual = entry.GetValue()->GetDoubleArray();
|
||||
EXPECT_EQ(expect.size(), actual.size());
|
||||
for (size_t i = 0; i < expect.size(); i++) {
|
||||
EXPECT_FLOAT_EQ(expect[i], actual[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardTabTest, AddBooleanArray) {
|
||||
std::array<bool, 2> expect = {{true, false}};
|
||||
auto entry = m_tab->Add("BoolArray", expect).GetEntry();
|
||||
EXPECT_EQ("/Shuffleboard/Tab/BoolArray", entry.GetName());
|
||||
|
||||
auto actual = entry.GetValue()->GetBooleanArray();
|
||||
EXPECT_EQ(expect.size(), actual.size());
|
||||
for (size_t i = 0; i < expect.size(); i++) {
|
||||
EXPECT_EQ(expect[i], actual[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ShuffleboardTabTest, AddStringArray) {
|
||||
std::array<std::string, 2> expect = {{"foo", "bar"}};
|
||||
auto entry = m_tab->Add("StringArray", expect).GetEntry();
|
||||
EXPECT_EQ("/Shuffleboard/Tab/StringArray", entry.GetName());
|
||||
|
||||
auto actual = entry.GetValue()->GetStringArray();
|
||||
EXPECT_EQ(expect.size(), actual.size());
|
||||
for (size_t i = 0; i < expect.size(); i++) {
|
||||
EXPECT_EQ(expect[i], actual[i]);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "frc/shuffleboard/Shuffleboard.h"
|
||||
#include "frc/shuffleboard/ShuffleboardTab.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
class ShuffleboardTest : public testing::Test {};
|
||||
|
||||
TEST_F(ShuffleboardTest, TabObjectsCached) {
|
||||
ShuffleboardTab& tab1 = Shuffleboard::GetTab("testTabObjectsCached");
|
||||
ShuffleboardTab& tab2 = Shuffleboard::GetTab("testTabObjectsCached");
|
||||
EXPECT_EQ(&tab1, &tab2) << "Tab objects were not cached";
|
||||
}
|
||||
Reference in New Issue
Block a user