2022-06-16 09:32:16 +03:00
|
|
|
// 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 "CommandTestBase.h"
|
2022-08-30 07:53:47 +03:00
|
|
|
#include "frc2/command/Command.h"
|
2022-06-16 09:32:16 +03:00
|
|
|
#include "frc2/command/CommandHelper.h"
|
|
|
|
|
#include "frc2/command/RunCommand.h"
|
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
|
|
using namespace frc2;
|
|
|
|
|
|
2022-08-30 07:53:47 +03:00
|
|
|
class SchedulingRecursionTest
|
|
|
|
|
: public CommandTestBaseWithParam<Command::InterruptionBehavior> {};
|
2022-06-16 09:32:16 +03:00
|
|
|
|
|
|
|
|
class SelfCancellingCommand
|
|
|
|
|
: public CommandHelper<CommandBase, SelfCancellingCommand> {
|
|
|
|
|
public:
|
2022-08-30 07:53:47 +03:00
|
|
|
SelfCancellingCommand(CommandScheduler* scheduler, Subsystem* requirement,
|
|
|
|
|
Command::InterruptionBehavior interruptionBehavior =
|
|
|
|
|
Command::InterruptionBehavior::kCancelSelf)
|
|
|
|
|
: m_scheduler(scheduler), m_interrupt(interruptionBehavior) {
|
2022-06-16 09:32:16 +03:00
|
|
|
AddRequirements(requirement);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Initialize() override { m_scheduler->Cancel(this); }
|
|
|
|
|
|
2022-08-30 07:53:47 +03:00
|
|
|
InterruptionBehavior GetInterruptionBehavior() const override {
|
|
|
|
|
return m_interrupt;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-16 09:32:16 +03:00
|
|
|
private:
|
|
|
|
|
CommandScheduler* m_scheduler;
|
2022-08-30 07:53:47 +03:00
|
|
|
InterruptionBehavior m_interrupt;
|
2022-06-16 09:32:16 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks <a
|
|
|
|
|
* href="https://github.com/wpilibsuite/allwpilib/issues/4259">wpilibsuite/allwpilib#4259</a>.
|
|
|
|
|
*/
|
2022-08-30 07:53:47 +03:00
|
|
|
TEST_F(SchedulingRecursionTest, CancelFromInitialize) {
|
2022-06-16 09:32:16 +03:00
|
|
|
CommandScheduler scheduler = GetScheduler();
|
|
|
|
|
bool hasOtherRun = false;
|
|
|
|
|
TestSubsystem requirement;
|
2022-08-30 07:53:47 +03:00
|
|
|
auto selfCancels = SelfCancellingCommand(&scheduler, &requirement);
|
2022-06-16 09:32:16 +03:00
|
|
|
RunCommand other =
|
|
|
|
|
RunCommand([&hasOtherRun] { hasOtherRun = true; }, {&requirement});
|
|
|
|
|
|
2022-08-30 07:53:47 +03:00
|
|
|
scheduler.Schedule(&selfCancels);
|
2022-06-16 09:32:16 +03:00
|
|
|
scheduler.Run();
|
|
|
|
|
scheduler.Schedule(&other);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(scheduler.IsScheduled(&selfCancels));
|
|
|
|
|
EXPECT_TRUE(scheduler.IsScheduled(&other));
|
|
|
|
|
scheduler.Run();
|
|
|
|
|
EXPECT_TRUE(hasOtherRun);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-30 07:53:47 +03:00
|
|
|
TEST_P(SchedulingRecursionTest,
|
2022-12-15 21:53:08 -08:00
|
|
|
DISABLED_DefaultCommandGetsRescheduledAfterSelfCanceling) {
|
2022-06-16 09:32:16 +03:00
|
|
|
CommandScheduler scheduler = GetScheduler();
|
|
|
|
|
bool hasOtherRun = false;
|
|
|
|
|
TestSubsystem requirement;
|
2022-08-30 07:53:47 +03:00
|
|
|
auto selfCancels =
|
|
|
|
|
SelfCancellingCommand(&scheduler, &requirement, GetParam());
|
2022-06-16 09:32:16 +03:00
|
|
|
RunCommand other =
|
|
|
|
|
RunCommand([&hasOtherRun] { hasOtherRun = true; }, {&requirement});
|
|
|
|
|
scheduler.SetDefaultCommand(&requirement, std::move(other));
|
|
|
|
|
|
2022-08-30 07:53:47 +03:00
|
|
|
scheduler.Schedule(&selfCancels);
|
2022-06-16 09:32:16 +03:00
|
|
|
scheduler.Run();
|
|
|
|
|
scheduler.Run();
|
|
|
|
|
EXPECT_FALSE(scheduler.IsScheduled(&selfCancels));
|
|
|
|
|
EXPECT_TRUE(scheduler.IsScheduled(scheduler.GetDefaultCommand(&requirement)));
|
|
|
|
|
scheduler.Run();
|
|
|
|
|
EXPECT_TRUE(hasOtherRun);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class CancelEndCommand : public CommandHelper<CommandBase, CancelEndCommand> {
|
|
|
|
|
public:
|
|
|
|
|
CancelEndCommand(CommandScheduler* scheduler, int& counter)
|
|
|
|
|
: m_scheduler(scheduler), m_counter(counter) {}
|
|
|
|
|
|
|
|
|
|
void End(bool interrupted) override {
|
|
|
|
|
m_counter++;
|
|
|
|
|
m_scheduler->Cancel(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
CommandScheduler* m_scheduler;
|
|
|
|
|
int& m_counter;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TEST_F(SchedulingRecursionTest, CancelFromEnd) {
|
|
|
|
|
CommandScheduler scheduler = GetScheduler();
|
|
|
|
|
int counter = 0;
|
|
|
|
|
CancelEndCommand selfCancels{&scheduler, counter};
|
|
|
|
|
|
|
|
|
|
scheduler.Schedule(&selfCancels);
|
|
|
|
|
|
|
|
|
|
EXPECT_NO_THROW({ scheduler.Cancel(&selfCancels); });
|
|
|
|
|
EXPECT_EQ(1, counter);
|
|
|
|
|
EXPECT_FALSE(scheduler.IsScheduled(&selfCancels));
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-30 07:53:47 +03:00
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
|
|
|
SchedulingRecursionTests, SchedulingRecursionTest,
|
|
|
|
|
testing::Values(Command::InterruptionBehavior::kCancelSelf,
|
|
|
|
|
Command::InterruptionBehavior::kCancelIncoming));
|