From c4fc21838fe5e994135f7bfc0f6d85f93a1fd2df Mon Sep 17 00:00:00 2001 From: Starlight220 <53231611+Starlight220@users.noreply.github.com> Date: Fri, 23 Jun 2023 18:21:05 +0300 Subject: [PATCH] [commands] Add ConditionalCommand getInterruptionBehavior (#5161) --- .../wpilibj2/command/ConditionalCommand.java | 10 ++ .../cpp/frc2/command/ConditionalCommand.cpp | 12 +++ .../include/frc2/command/ConditionalCommand.h | 2 + .../command/ConditionalCommandTest.java | 96 +++++++++++++++++++ .../frc2/command/ConditionalCommandTest.cpp | 85 ++++++++++++++++ 5 files changed, 205 insertions(+) diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ConditionalCommand.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ConditionalCommand.java index 782f2179fe..6bda65d5cc 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ConditionalCommand.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ConditionalCommand.java @@ -73,6 +73,16 @@ public class ConditionalCommand extends CommandBase { return m_onTrue.runsWhenDisabled() && m_onFalse.runsWhenDisabled(); } + @Override + public InterruptionBehavior getInterruptionBehavior() { + if (m_onTrue.getInterruptionBehavior() == InterruptionBehavior.kCancelSelf + || m_onFalse.getInterruptionBehavior() == InterruptionBehavior.kCancelSelf) { + return InterruptionBehavior.kCancelSelf; + } else { + return InterruptionBehavior.kCancelIncoming; + } + } + @Override public void initSendable(SendableBuilder builder) { super.initSendable(builder); diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/ConditionalCommand.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/ConditionalCommand.cpp index 2610c96b78..e8d083bd52 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/ConditionalCommand.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/ConditionalCommand.cpp @@ -53,6 +53,18 @@ bool ConditionalCommand::RunsWhenDisabled() const { return m_runsWhenDisabled; } +Command::InterruptionBehavior ConditionalCommand::GetInterruptionBehavior() + const { + if (m_onTrue->GetInterruptionBehavior() == + InterruptionBehavior::kCancelSelf || + m_onFalse->GetInterruptionBehavior() == + InterruptionBehavior::kCancelSelf) { + return InterruptionBehavior::kCancelSelf; + } else { + return InterruptionBehavior::kCancelIncoming; + } +} + void ConditionalCommand::InitSendable(wpi::SendableBuilder& builder) { CommandBase::InitSendable(builder); builder.AddStringProperty( diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/ConditionalCommand.h b/wpilibNewCommands/src/main/native/include/frc2/command/ConditionalCommand.h index ce9cb473fe..20a2a1272a 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/ConditionalCommand.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/ConditionalCommand.h @@ -72,6 +72,8 @@ class ConditionalCommand bool RunsWhenDisabled() const override; + InterruptionBehavior GetInterruptionBehavior() const override; + void InitSendable(wpi::SendableBuilder& builder) override; private: diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ConditionalCommandTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ConditionalCommandTest.java index 420a8a70b6..4659f0ec3d 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ConditionalCommandTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ConditionalCommandTest.java @@ -4,11 +4,19 @@ package edu.wpi.first.wpilibj2.command; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import edu.wpi.first.wpilibj2.command.Command.InterruptionBehavior; +import java.util.function.BooleanSupplier; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; class ConditionalCommandTest extends CommandTestBase { @Test @@ -60,4 +68,92 @@ class ConditionalCommandTest extends CommandTestBase { verify(command2, never()).end(true); } } + + static Stream interruptible() { + return Stream.of( + arguments( + "AllCancelSelf", + InterruptionBehavior.kCancelSelf, + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelSelf), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelSelf), + (BooleanSupplier) () -> true), + arguments( + "AllCancelIncoming", + InterruptionBehavior.kCancelIncoming, + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelIncoming), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelIncoming), + (BooleanSupplier) () -> true), + arguments( + "OneCancelSelfOneIncoming", + InterruptionBehavior.kCancelSelf, + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelSelf), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelIncoming), + (BooleanSupplier) () -> true), + arguments( + "OneCancelIncomingOneSelf", + InterruptionBehavior.kCancelSelf, + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelIncoming), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelSelf), + (BooleanSupplier) () -> true)); + } + + @MethodSource + @ParameterizedTest(name = "interruptible[{index}]: {0}") + void interruptible( + @SuppressWarnings("unused") String name, + InterruptionBehavior expected, + Command command1, + Command command2, + BooleanSupplier selector) { + var command = Commands.either(command1, command2, selector); + assertEquals(expected, command.getInterruptionBehavior()); + } + + static Stream runsWhenDisabled() { + return Stream.of( + arguments( + "AllFalse", + false, + new WaitUntilCommand(() -> false).ignoringDisable(false), + new WaitUntilCommand(() -> false).ignoringDisable(false), + (BooleanSupplier) () -> true), + arguments( + "AllTrue", + true, + new WaitUntilCommand(() -> false).ignoringDisable(true), + new WaitUntilCommand(() -> false).ignoringDisable(true), + (BooleanSupplier) () -> true), + arguments( + "OneTrueOneFalse", + false, + new WaitUntilCommand(() -> false).ignoringDisable(true), + new WaitUntilCommand(() -> false).ignoringDisable(false), + (BooleanSupplier) () -> true), + arguments( + "OneFalseOneTrue", + false, + new WaitUntilCommand(() -> false).ignoringDisable(false), + new WaitUntilCommand(() -> false).ignoringDisable(true), + (BooleanSupplier) () -> true)); + } + + @MethodSource + @ParameterizedTest(name = "runsWhenDisabled[{index}]: {0}") + void runsWhenDisabled( + @SuppressWarnings("unused") String name, + boolean expected, + Command command1, + Command command2, + BooleanSupplier selector) { + var command = Commands.either(command1, command2, selector); + assertEquals(expected, command.runsWhenDisabled()); + } } diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/ConditionalCommandTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/ConditionalCommandTest.cpp index 27b89e58b7..a82d834f3a 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/ConditionalCommandTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/ConditionalCommandTest.cpp @@ -3,6 +3,7 @@ // the WPILib BSD license file in the root directory of this project. #include "CommandTestBase.h" +#include "frc2/command/Commands.h" #include "frc2/command/ConditionalCommand.h" #include "frc2/command/InstantCommand.h" #include "frc2/command/SelectCommand.h" @@ -51,3 +52,87 @@ TEST_F(ConditionalCommandTest, ConditionalCommandRequirement) { EXPECT_TRUE(scheduler.IsScheduled(&command3)); EXPECT_FALSE(scheduler.IsScheduled(&conditional)); } + +TEST_F(ConditionalCommandTest, AllTrue) { + CommandPtr command = + cmd::Either(cmd::WaitUntil([] { return false; }).IgnoringDisable(true), + cmd::WaitUntil([] { return false; }).IgnoringDisable(true), + [] { return true; }); + EXPECT_EQ(true, command.get()->RunsWhenDisabled()); +} + +TEST_F(ConditionalCommandTest, AllFalse) { + CommandPtr command = + cmd::Either(cmd::WaitUntil([] { return false; }).IgnoringDisable(false), + cmd::WaitUntil([] { return false; }).IgnoringDisable(false), + [] { return true; }); + EXPECT_EQ(false, command.get()->RunsWhenDisabled()); +} + +TEST_F(ConditionalCommandTest, OneTrueOneFalse) { + CommandPtr command = + cmd::Either(cmd::WaitUntil([] { return false; }).IgnoringDisable(true), + cmd::WaitUntil([] { return false; }).IgnoringDisable(false), + [] { return true; }); + EXPECT_EQ(false, command.get()->RunsWhenDisabled()); +} + +TEST_F(ConditionalCommandTest, TwoFalseOneTrue) { + CommandPtr command = + cmd::Either(cmd::WaitUntil([] { return false; }).IgnoringDisable(false), + cmd::WaitUntil([] { return false; }).IgnoringDisable(true), + [] { return true; }); + EXPECT_EQ(false, command.get()->RunsWhenDisabled()); +} + +TEST_F(ConditionalCommandTest, AllCancelSelf) { + CommandPtr command = cmd::Either( + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelSelf), + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelSelf), + [] { return true; }); + EXPECT_EQ(Command::InterruptionBehavior::kCancelSelf, + command.get()->GetInterruptionBehavior()); +} + +TEST_F(ConditionalCommandTest, AllCancelIncoming) { + CommandPtr command = cmd::Either( + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelIncoming), + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelIncoming), + [] { return false; }); + EXPECT_EQ(Command::InterruptionBehavior::kCancelIncoming, + command.get()->GetInterruptionBehavior()); +} + +TEST_F(ConditionalCommandTest, OneCancelSelfOneIncoming) { + CommandPtr command = cmd::Either( + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelSelf), + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelIncoming), + [] { return false; }); + EXPECT_EQ(Command::InterruptionBehavior::kCancelSelf, + command.get()->GetInterruptionBehavior()); +} + +TEST_F(ConditionalCommandTest, OneCancelIncomingOneSelf) { + CommandPtr command = cmd::Either( + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelIncoming), + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelSelf), + [] { return false; }); + EXPECT_EQ(Command::InterruptionBehavior::kCancelSelf, + command.get()->GetInterruptionBehavior()); +}