diff --git a/styleguide/spotbugs-exclude.xml b/styleguide/spotbugs-exclude.xml index 0c0156d346..58d82d1e74 100644 --- a/styleguide/spotbugs-exclude.xml +++ b/styleguide/spotbugs-exclude.xml @@ -64,6 +64,10 @@ + + + + diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelCommandGroup.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelCommandGroup.java index fa6ab8db92..40a85a714c 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelCommandGroup.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelCommandGroup.java @@ -19,6 +19,7 @@ public class ParallelCommandGroup extends CommandGroupBase { // maps commands in this group to whether they are still running private final Map m_commands = new HashMap<>(); private boolean m_runWhenDisabled = true; + private InterruptionBehavior m_interruptBehavior = InterruptionBehavior.kCancelIncoming; /** * Creates a new ParallelCommandGroup. The given commands will be executed simultaneously. The @@ -50,6 +51,9 @@ public class ParallelCommandGroup extends CommandGroupBase { m_commands.put(command, false); m_requirements.addAll(command.getRequirements()); m_runWhenDisabled &= command.runsWhenDisabled(); + if (command.getInterruptionBehavior() == InterruptionBehavior.kCancelSelf) { + m_interruptBehavior = InterruptionBehavior.kCancelSelf; + } } } @@ -95,4 +99,9 @@ public class ParallelCommandGroup extends CommandGroupBase { public boolean runsWhenDisabled() { return m_runWhenDisabled; } + + @Override + public InterruptionBehavior getInterruptionBehavior() { + return m_interruptBehavior; + } } diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelDeadlineGroup.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelDeadlineGroup.java index f0e192958e..e3ac8fd85f 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelDeadlineGroup.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelDeadlineGroup.java @@ -22,6 +22,7 @@ public class ParallelDeadlineGroup extends CommandGroupBase { private boolean m_runWhenDisabled = true; private boolean m_finished = true; private Command m_deadline; + private InterruptionBehavior m_interruptBehavior = InterruptionBehavior.kCancelIncoming; /** * Creates a new ParallelDeadlineGroup. The given commands (including the deadline) will be @@ -72,6 +73,9 @@ public class ParallelDeadlineGroup extends CommandGroupBase { m_commands.put(command, false); m_requirements.addAll(command.getRequirements()); m_runWhenDisabled &= command.runsWhenDisabled(); + if (command.getInterruptionBehavior() == InterruptionBehavior.kCancelSelf) { + m_interruptBehavior = InterruptionBehavior.kCancelSelf; + } } } @@ -119,4 +123,9 @@ public class ParallelDeadlineGroup extends CommandGroupBase { public boolean runsWhenDisabled() { return m_runWhenDisabled; } + + @Override + public InterruptionBehavior getInterruptionBehavior() { + return m_interruptBehavior; + } } diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroup.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroup.java index edbb83d6de..43172af6df 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroup.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroup.java @@ -20,6 +20,7 @@ public class ParallelRaceGroup extends CommandGroupBase { private final Set m_commands = new HashSet<>(); private boolean m_runWhenDisabled = true; private boolean m_finished = true; + private InterruptionBehavior m_interruptBehavior = InterruptionBehavior.kCancelIncoming; /** * Creates a new ParallelCommandRace. The given commands will be executed simultaneously, and will @@ -51,6 +52,9 @@ public class ParallelRaceGroup extends CommandGroupBase { m_commands.add(command); m_requirements.addAll(command.getRequirements()); m_runWhenDisabled &= command.runsWhenDisabled(); + if (command.getInterruptionBehavior() == InterruptionBehavior.kCancelSelf) { + m_interruptBehavior = InterruptionBehavior.kCancelSelf; + } } } @@ -88,4 +92,9 @@ public class ParallelRaceGroup extends CommandGroupBase { public boolean runsWhenDisabled() { return m_runWhenDisabled; } + + @Override + public InterruptionBehavior getInterruptionBehavior() { + return m_interruptBehavior; + } } diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SelectCommand.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SelectCommand.java index e7748160cd..3cf9f261fb 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SelectCommand.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SelectCommand.java @@ -31,6 +31,8 @@ public class SelectCommand extends CommandBase { private final Supplier m_selector; private final Supplier m_toRun; private Command m_selectedCommand; + private boolean m_runsWhenDisabled = true; + private InterruptionBehavior m_interruptBehavior = InterruptionBehavior.kCancelIncoming; /** * Creates a new selectcommand. @@ -50,6 +52,10 @@ public class SelectCommand extends CommandBase { for (Command command : m_commands.values()) { m_requirements.addAll(command.getRequirements()); + m_runsWhenDisabled &= command.runsWhenDisabled(); + if (command.getInterruptionBehavior() == InterruptionBehavior.kCancelSelf) { + m_interruptBehavior = InterruptionBehavior.kCancelSelf; + } } } @@ -62,6 +68,10 @@ public class SelectCommand extends CommandBase { m_commands = null; m_selector = null; m_toRun = requireNonNullParam(toRun, "toRun", "SelectCommand"); + + // we have no way of checking the underlying command, so default. + m_runsWhenDisabled = false; + m_interruptBehavior = InterruptionBehavior.kCancelSelf; } @Override @@ -97,14 +107,11 @@ public class SelectCommand extends CommandBase { @Override public boolean runsWhenDisabled() { - if (m_commands != null) { - boolean runsWhenDisabled = true; - for (Command command : m_commands.values()) { - runsWhenDisabled &= command.runsWhenDisabled(); - } - return runsWhenDisabled; - } else { - return m_toRun.get().runsWhenDisabled(); - } + return m_runsWhenDisabled; + } + + @Override + public InterruptionBehavior getInterruptionBehavior() { + return m_interruptBehavior; } } diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SequentialCommandGroup.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SequentialCommandGroup.java index f028e5ed56..4d1f44cefa 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SequentialCommandGroup.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SequentialCommandGroup.java @@ -18,6 +18,7 @@ public class SequentialCommandGroup extends CommandGroupBase { private final List m_commands = new ArrayList<>(); private int m_currentCommandIndex = -1; private boolean m_runWhenDisabled = true; + private InterruptionBehavior m_interruptBehavior = InterruptionBehavior.kCancelIncoming; /** * Creates a new SequentialCommandGroup. The given commands will be run sequentially, with the @@ -44,6 +45,9 @@ public class SequentialCommandGroup extends CommandGroupBase { m_commands.add(command); m_requirements.addAll(command.getRequirements()); m_runWhenDisabled &= command.runsWhenDisabled(); + if (command.getInterruptionBehavior() == InterruptionBehavior.kCancelSelf) { + m_interruptBehavior = InterruptionBehavior.kCancelSelf; + } } } @@ -94,4 +98,9 @@ public class SequentialCommandGroup extends CommandGroupBase { public boolean runsWhenDisabled() { return m_runWhenDisabled; } + + @Override + public InterruptionBehavior getInterruptionBehavior() { + return m_interruptBehavior; + } } diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelCommandGroup.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelCommandGroup.cpp index d6169d7574..53f0ca7634 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelCommandGroup.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelCommandGroup.cpp @@ -56,6 +56,11 @@ bool ParallelCommandGroup::RunsWhenDisabled() const { return m_runWhenDisabled; } +Command::InterruptionBehavior ParallelCommandGroup::GetInterruptionBehavior() + const { + return m_interruptBehavior; +} + void ParallelCommandGroup::AddCommands( std::vector>&& commands) { for (auto&& command : commands) { @@ -75,6 +80,10 @@ void ParallelCommandGroup::AddCommands( command->SetGrouped(true); AddRequirements(command->GetRequirements()); m_runWhenDisabled &= command->RunsWhenDisabled(); + if (command->GetInterruptionBehavior() == + Command::InterruptionBehavior::kCancelSelf) { + m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf; + } m_commands.emplace_back(std::move(command), false); } else { throw FRC_MakeError(frc::err::CommandIllegalUse, diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelDeadlineGroup.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelDeadlineGroup.cpp index 16104e2513..35d5f0fb4a 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelDeadlineGroup.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelDeadlineGroup.cpp @@ -53,6 +53,11 @@ bool ParallelDeadlineGroup::RunsWhenDisabled() const { return m_runWhenDisabled; } +Command::InterruptionBehavior ParallelDeadlineGroup::GetInterruptionBehavior() + const { + return m_interruptBehavior; +} + void ParallelDeadlineGroup::AddCommands( std::vector>&& commands) { if (!RequireUngrouped(commands)) { @@ -70,6 +75,10 @@ void ParallelDeadlineGroup::AddCommands( command->SetGrouped(true); AddRequirements(command->GetRequirements()); m_runWhenDisabled &= command->RunsWhenDisabled(); + if (command->GetInterruptionBehavior() == + Command::InterruptionBehavior::kCancelSelf) { + m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf; + } m_commands.emplace_back(std::move(command), false); } else { throw FRC_MakeError(frc::err::CommandIllegalUse, diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelRaceGroup.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelRaceGroup.cpp index 38e0494b79..9a62b41e02 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelRaceGroup.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/ParallelRaceGroup.cpp @@ -43,6 +43,11 @@ bool ParallelRaceGroup::RunsWhenDisabled() const { return m_runWhenDisabled; } +Command::InterruptionBehavior ParallelRaceGroup::GetInterruptionBehavior() + const { + return m_interruptBehavior; +} + void ParallelRaceGroup::AddCommands( std::vector>&& commands) { if (!RequireUngrouped(commands)) { @@ -60,6 +65,10 @@ void ParallelRaceGroup::AddCommands( command->SetGrouped(true); AddRequirements(command->GetRequirements()); m_runWhenDisabled &= command->RunsWhenDisabled(); + if (command->GetInterruptionBehavior() == + Command::InterruptionBehavior::kCancelSelf) { + m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf; + } m_commands.emplace_back(std::move(command)); } else { throw FRC_MakeError(frc::err::CommandIllegalUse, diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/SequentialCommandGroup.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/SequentialCommandGroup.cpp index a02870724a..ad25eff1c2 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/SequentialCommandGroup.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/SequentialCommandGroup.cpp @@ -53,6 +53,11 @@ bool SequentialCommandGroup::RunsWhenDisabled() const { return m_runWhenDisabled; } +Command::InterruptionBehavior SequentialCommandGroup::GetInterruptionBehavior() + const { + return m_interruptBehavior; +} + void SequentialCommandGroup::AddCommands( std::vector>&& commands) { if (!RequireUngrouped(commands)) { @@ -69,6 +74,10 @@ void SequentialCommandGroup::AddCommands( command->SetGrouped(true); AddRequirements(command->GetRequirements()); m_runWhenDisabled &= command->RunsWhenDisabled(); + if (command->GetInterruptionBehavior() == + Command::InterruptionBehavior::kCancelSelf) { + m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf; + } m_commands.emplace_back(std::move(command)); } } diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/ParallelCommandGroup.h b/wpilibNewCommands/src/main/native/include/frc2/command/ParallelCommandGroup.h index 2392b2ad09..cf7059b858 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/ParallelCommandGroup.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/ParallelCommandGroup.h @@ -84,11 +84,15 @@ class ParallelCommandGroup bool RunsWhenDisabled() const override; + Command::InterruptionBehavior GetInterruptionBehavior() const override; + private: void AddCommands(std::vector>&& commands) final; std::vector, bool>> m_commands; bool m_runWhenDisabled{true}; + Command::InterruptionBehavior m_interruptBehavior{ + Command::InterruptionBehavior::kCancelIncoming}; bool isRunning = false; }; } // namespace frc2 diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/ParallelDeadlineGroup.h b/wpilibNewCommands/src/main/native/include/frc2/command/ParallelDeadlineGroup.h index 3ef8b78a8b..831a22e20d 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/ParallelDeadlineGroup.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/ParallelDeadlineGroup.h @@ -92,6 +92,8 @@ class ParallelDeadlineGroup bool RunsWhenDisabled() const override; + Command::InterruptionBehavior GetInterruptionBehavior() const override; + private: void AddCommands(std::vector>&& commands) final; @@ -100,6 +102,8 @@ class ParallelDeadlineGroup std::vector, bool>> m_commands; Command* m_deadline; bool m_runWhenDisabled{true}; + Command::InterruptionBehavior m_interruptBehavior{ + Command::InterruptionBehavior::kCancelIncoming}; bool m_finished{true}; }; } // namespace frc2 diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/ParallelRaceGroup.h b/wpilibNewCommands/src/main/native/include/frc2/command/ParallelRaceGroup.h index 2f7ee19a71..365730efc1 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/ParallelRaceGroup.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/ParallelRaceGroup.h @@ -72,11 +72,15 @@ class ParallelRaceGroup bool RunsWhenDisabled() const override; + Command::InterruptionBehavior GetInterruptionBehavior() const override; + private: void AddCommands(std::vector>&& commands) final; std::vector> m_commands; bool m_runWhenDisabled{true}; + Command::InterruptionBehavior m_interruptBehavior{ + Command::InterruptionBehavior::kCancelIncoming}; bool m_finished{false}; bool isRunning = false; }; diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/SelectCommand.h b/wpilibNewCommands/src/main/native/include/frc2/command/SelectCommand.h index 6e1b2bd7f5..202474ef7c 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/SelectCommand.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/SelectCommand.h @@ -69,6 +69,10 @@ class SelectCommand : public CommandHelper> { for (auto&& command : foo) { this->AddRequirements(command.second->GetRequirements()); m_runsWhenDisabled &= command.second->RunsWhenDisabled(); + if (command.second->GetInterruptionBehavior() == + Command::InterruptionBehavior::kCancelSelf) { + m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf; + } m_commands.emplace(std::move(command.first), std::move(command.second)); } } @@ -86,6 +90,10 @@ class SelectCommand : public CommandHelper> { for (auto&& command : commands) { this->AddRequirements(command.second->GetRequirements()); m_runsWhenDisabled &= command.second->RunsWhenDisabled(); + if (command.second->GetInterruptionBehavior() == + Command::InterruptionBehavior::kCancelSelf) { + m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf; + } m_commands.emplace(std::move(command.first), std::move(command.second)); } } @@ -118,6 +126,10 @@ class SelectCommand : public CommandHelper> { bool RunsWhenDisabled() const override { return m_runsWhenDisabled; } + Command::InterruptionBehavior GetInterruptionBehavior() const override { + return m_interruptBehavior; + } + protected: std::unique_ptr TransferOwnership() && override { return std::make_unique(std::move(*this)); @@ -129,6 +141,8 @@ class SelectCommand : public CommandHelper> { std::function m_toRun; Command* m_selectedCommand; bool m_runsWhenDisabled = true; + Command::InterruptionBehavior m_interruptBehavior{ + Command::InterruptionBehavior::kCancelIncoming}; }; template diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/SequentialCommandGroup.h b/wpilibNewCommands/src/main/native/include/frc2/command/SequentialCommandGroup.h index bdcf2efa08..255bbea671 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/SequentialCommandGroup.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/SequentialCommandGroup.h @@ -87,12 +87,16 @@ class SequentialCommandGroup bool RunsWhenDisabled() const override; + Command::InterruptionBehavior GetInterruptionBehavior() const override; + private: void AddCommands(std::vector>&& commands) final; wpi::SmallVector, 4> m_commands; size_t m_currentCommandIndex{invalid_index}; bool m_runWhenDisabled{true}; + Command::InterruptionBehavior m_interruptBehavior{ + Command::InterruptionBehavior::kCancelIncoming}; }; } // namespace frc2 diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandTestBase.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandTestBase.java index 0876de1504..ecd3e9b6d4 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandTestBase.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandTestBase.java @@ -9,6 +9,7 @@ import static org.mockito.Mockito.when; import edu.wpi.first.wpilibj.DriverStation; import edu.wpi.first.wpilibj.simulation.DriverStationSim; +import edu.wpi.first.wpilibj2.command.Command.InterruptionBehavior; import java.util.Set; import org.junit.jupiter.api.BeforeEach; @@ -47,6 +48,7 @@ public class CommandTestBase { when(m_mockCommand.getRequirements()).thenReturn(Set.of(requirements)); when(m_mockCommand.isFinished()).thenReturn(false); when(m_mockCommand.runsWhenDisabled()).thenReturn(runWhenDisabled); + when(m_mockCommand.getInterruptionBehavior()).thenReturn(InterruptionBehavior.kCancelSelf); } public Command getMock() { diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/MultiCompositionTestBase.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/MultiCompositionTestBase.java new file mode 100644 index 0000000000..2b79550cb7 --- /dev/null +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/MultiCompositionTestBase.java @@ -0,0 +1,115 @@ +// 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. + +package edu.wpi.first.wpilibj2.command; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import edu.wpi.first.wpilibj2.command.Command.InterruptionBehavior; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +interface MultiCompositionTestBase extends SingleCompositionTestBase { + T compose(Command... members); + + @Override + default T composeSingle(Command member) { + return compose(member); + } + + static Stream interruptible() { + return Stream.of( + arguments( + "AllCancelSelf", + InterruptionBehavior.kCancelSelf, + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelSelf), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelSelf), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelSelf)), + arguments( + "AllCancelIncoming", + InterruptionBehavior.kCancelIncoming, + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelIncoming), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelIncoming), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelIncoming)), + arguments( + "TwoCancelSelfOneIncoming", + InterruptionBehavior.kCancelSelf, + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelSelf), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelSelf), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelIncoming)), + arguments( + "TwoCancelIncomingOneSelf", + InterruptionBehavior.kCancelSelf, + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelIncoming), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelIncoming), + new WaitUntilCommand(() -> false) + .withInterruptBehavior(InterruptionBehavior.kCancelSelf))); + } + + @MethodSource + @ParameterizedTest(name = "interruptible[{index}]: {0}") + default void interruptible( + @SuppressWarnings("unused") String name, + InterruptionBehavior expected, + Command command1, + Command command2, + Command command3) { + var command = compose(command1, command2, command3); + assertEquals(expected, command.getInterruptionBehavior()); + } + + static Stream runsWhenDisabled() { + return Stream.of( + arguments( + "AllFalse", + false, + new WaitUntilCommand(() -> false).ignoringDisable(false), + new WaitUntilCommand(() -> false).ignoringDisable(false), + new WaitUntilCommand(() -> false).ignoringDisable(false)), + arguments( + "AllTrue", + true, + new WaitUntilCommand(() -> false).ignoringDisable(true), + new WaitUntilCommand(() -> false).ignoringDisable(true), + new WaitUntilCommand(() -> false).ignoringDisable(true)), + arguments( + "TwoTrueOneFalse", + false, + new WaitUntilCommand(() -> false).ignoringDisable(true), + new WaitUntilCommand(() -> false).ignoringDisable(true), + new WaitUntilCommand(() -> false).ignoringDisable(false)), + arguments( + "TwoFalseOneTrue", + false, + new WaitUntilCommand(() -> false).ignoringDisable(false), + new WaitUntilCommand(() -> false).ignoringDisable(false), + new WaitUntilCommand(() -> false).ignoringDisable(true))); + } + + @MethodSource + @ParameterizedTest(name = "runsWhenDisabled[{index}]: {0}") + default void runsWhenDisabled( + @SuppressWarnings("unused") String name, + boolean expected, + Command command1, + Command command2, + Command command3) { + var command = compose(command1, command2, command3); + assertEquals(expected, command.runsWhenDisabled()); + } +} diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelCommandGroupTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelCommandGroupTest.java index 5bdc56bf8d..7dc91106ee 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelCommandGroupTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelCommandGroupTest.java @@ -14,7 +14,8 @@ import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Test; -class ParallelCommandGroupTest extends CommandTestBase { +class ParallelCommandGroupTest extends CommandTestBase + implements MultiCompositionTestBase { @Test void parallelGroupScheduleTest() { try (CommandScheduler scheduler = new CommandScheduler()) { @@ -126,4 +127,9 @@ class ParallelCommandGroupTest extends CommandTestBase { assertThrows( IllegalArgumentException.class, () -> new ParallelCommandGroup(command1, command2)); } + + @Override + public ParallelCommandGroup compose(Command... members) { + return new ParallelCommandGroup(members); + } } diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelDeadlineGroupTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelDeadlineGroupTest.java index 236497e171..6fa644bb24 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelDeadlineGroupTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelDeadlineGroupTest.java @@ -11,9 +11,11 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.internal.verification.VerificationModeFactory.times; +import java.util.Arrays; import org.junit.jupiter.api.Test; -class ParallelDeadlineGroupTest extends CommandTestBase { +class ParallelDeadlineGroupTest extends CommandTestBase + implements MultiCompositionTestBase { @Test void parallelDeadlineScheduleTest() { try (CommandScheduler scheduler = new CommandScheduler()) { @@ -122,4 +124,9 @@ class ParallelDeadlineGroupTest extends CommandTestBase { assertThrows( IllegalArgumentException.class, () -> new ParallelDeadlineGroup(command1, command2)); } + + @Override + public ParallelDeadlineGroup compose(Command... members) { + return new ParallelDeadlineGroup(members[0], Arrays.copyOfRange(members, 1, members.length)); + } } diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroupTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroupTest.java index 113bf1bde5..67524960ca 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroupTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroupTest.java @@ -16,7 +16,8 @@ import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Test; -class ParallelRaceGroupTest extends CommandTestBase { +class ParallelRaceGroupTest extends CommandTestBase + implements MultiCompositionTestBase { @Test void parallelRaceScheduleTest() { try (CommandScheduler scheduler = new CommandScheduler()) { @@ -202,4 +203,9 @@ class ParallelRaceGroupTest extends CommandTestBase { assertFalse(scheduler.isScheduled(group)); } } + + @Override + public ParallelRaceGroup compose(Command... members) { + return new ParallelRaceGroup(members); + } } diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/RepeatCommandTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/RepeatCommandTest.java index c05a0292c6..f082ddb92a 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/RepeatCommandTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/RepeatCommandTest.java @@ -9,11 +9,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.junit.jupiter.params.provider.ValueSource; -class RepeatCommandTest extends CommandTestBase { +class RepeatCommandTest extends CommandTestBase + implements SingleCompositionTestBase { @Test void callsMethodsCorrectly() { var initCounter = new AtomicInteger(0); @@ -66,18 +64,8 @@ class RepeatCommandTest extends CommandTestBase { assertEquals(1, endCounter.get()); } - @EnumSource(Command.InterruptionBehavior.class) - @ParameterizedTest - void interruptible(Command.InterruptionBehavior interruptionBehavior) { - var command = - new WaitUntilCommand(() -> false).withInterruptBehavior(interruptionBehavior).repeatedly(); - assertEquals(interruptionBehavior, command.getInterruptionBehavior()); - } - - @ValueSource(booleans = {true, false}) - @ParameterizedTest - void runWhenDisabled(boolean runsWhenDisabled) { - var command = new WaitUntilCommand(() -> false).ignoringDisable(runsWhenDisabled).repeatedly(); - assertEquals(runsWhenDisabled, command.runsWhenDisabled()); + @Override + public RepeatCommand composeSingle(Command member) { + return member.repeatedly(); } } diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SelectCommandTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SelectCommandTest.java index a4e4a29869..736f120a97 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SelectCommandTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SelectCommandTest.java @@ -9,10 +9,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.Test; -class SelectCommandTest extends CommandTestBase { +class SelectCommandTest extends CommandTestBase implements MultiCompositionTestBase { @Test void selectCommandTest() { try (CommandScheduler scheduler = new CommandScheduler()) { @@ -105,4 +106,13 @@ class SelectCommandTest extends CommandTestBase { verify(command3, never()).end(true); } } + + @Override + public SelectCommand compose(Command... members) { + var map = new HashMap(); + for (int i = 0; i < members.length; i++) { + map.put(i, members[i]); + } + return new SelectCommand(map, () -> 0); + } } diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SequentialCommandGroupTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SequentialCommandGroupTest.java index 7110b460ec..ff578f45d4 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SequentialCommandGroupTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SequentialCommandGroupTest.java @@ -12,7 +12,8 @@ import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Test; -class SequentialCommandGroupTest extends CommandTestBase { +class SequentialCommandGroupTest extends CommandTestBase + implements MultiCompositionTestBase { @Test void sequentialGroupScheduleTest() { try (CommandScheduler scheduler = new CommandScheduler()) { @@ -121,4 +122,9 @@ class SequentialCommandGroupTest extends CommandTestBase { assertTrue(scheduler.isScheduled(command3)); } } + + @Override + public SequentialCommandGroup compose(Command... members) { + return new SequentialCommandGroup(members); + } } diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SingleCompositionTestBase.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SingleCompositionTestBase.java new file mode 100644 index 0000000000..4e54e3ec00 --- /dev/null +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SingleCompositionTestBase.java @@ -0,0 +1,32 @@ +// 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. + +package edu.wpi.first.wpilibj2.command; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.ValueSource; + +public interface SingleCompositionTestBase { + T composeSingle(Command member); + + @EnumSource(Command.InterruptionBehavior.class) + @ParameterizedTest + default void interruptible(Command.InterruptionBehavior interruptionBehavior) { + var command = + composeSingle( + new WaitUntilCommand(() -> false).withInterruptBehavior(interruptionBehavior)); + assertEquals(interruptionBehavior, command.getInterruptionBehavior()); + } + + @ValueSource(booleans = {true, false}) + @ParameterizedTest + default void runWhenDisabled(boolean runsWhenDisabled) { + var command = + composeSingle(new WaitUntilCommand(() -> false).ignoringDisable(runsWhenDisabled)); + assertEquals(runsWhenDisabled, command.runsWhenDisabled()); + } +} diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CompositionTestBase.h b/wpilibNewCommands/src/test/native/cpp/frc2/command/CompositionTestBase.h new file mode 100644 index 0000000000..faa15122e7 --- /dev/null +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CompositionTestBase.h @@ -0,0 +1,204 @@ +// 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. + +#pragma once + +#include +#include + +#include "CommandTestBase.h" +#include "frc2/command/Commands.h" +#include "gtest/gtest.h" +#include "make_vector.h" + +namespace frc2 { + +inline namespace single { +template +class SingleCompositionRunsWhenDisabledTest : public CommandTestBase {}; + +TYPED_TEST_SUITE_P(SingleCompositionRunsWhenDisabledTest); + +TYPED_TEST_P(SingleCompositionRunsWhenDisabledTest, True) { + auto param = true; + TypeParam command = TypeParam( + cmd::WaitUntil([] { return false; }).IgnoringDisable(param).Unwrap()); + EXPECT_EQ(param, command.RunsWhenDisabled()); +} + +TYPED_TEST_P(SingleCompositionRunsWhenDisabledTest, False) { + auto param = false; + TypeParam command = TypeParam( + cmd::WaitUntil([] { return false; }).IgnoringDisable(param).Unwrap()); + EXPECT_EQ(param, command.RunsWhenDisabled()); +} + +REGISTER_TYPED_TEST_SUITE_P(SingleCompositionRunsWhenDisabledTest, True, False); + +template +class SingleCompositionInterruptibilityTest : public CommandTestBase {}; + +TYPED_TEST_SUITE_P(SingleCompositionInterruptibilityTest); + +TYPED_TEST_P(SingleCompositionInterruptibilityTest, CancelSelf) { + auto param = Command::InterruptionBehavior::kCancelSelf; + TypeParam command = TypeParam(cmd::WaitUntil([] { return false; }) + .WithInterruptBehavior(param) + .Unwrap()); + EXPECT_EQ(param, command.GetInterruptionBehavior()); +} + +TYPED_TEST_P(SingleCompositionInterruptibilityTest, CancelIncoming) { + auto param = Command::InterruptionBehavior::kCancelIncoming; + TypeParam command = TypeParam(cmd::WaitUntil([] { return false; }) + .WithInterruptBehavior(param) + .Unwrap()); + EXPECT_EQ(param, command.GetInterruptionBehavior()); +} + +REGISTER_TYPED_TEST_SUITE_P(SingleCompositionInterruptibilityTest, CancelSelf, + CancelIncoming); + +#define INSTANTIATE_SINGLE_COMMAND_COMPOSITION_TEST_SUITE(Suite, \ + CompositionType) \ + INSTANTIATE_TYPED_TEST_SUITE_P(Suite, SingleCompositionInterruptibilityTest, \ + CompositionType); \ + INSTANTIATE_TYPED_TEST_SUITE_P(Suite, SingleCompositionRunsWhenDisabledTest, \ + CompositionType); +} // namespace single + +inline namespace multi { +template +class MultiCompositionRunsWhenDisabledTest : public CommandTestBase {}; + +TYPED_TEST_SUITE_P(MultiCompositionRunsWhenDisabledTest); + +TYPED_TEST_P(MultiCompositionRunsWhenDisabledTest, OneTrue) { + auto param = true; + TypeParam command = TypeParam(CommandPtr::UnwrapVector(cmd::impl::MakeVector( + cmd::WaitUntil([] { return false; }).IgnoringDisable(param)))); + EXPECT_EQ(param, command.RunsWhenDisabled()); +} + +TYPED_TEST_P(MultiCompositionRunsWhenDisabledTest, OneFalse) { + auto param = false; + TypeParam command = TypeParam(CommandPtr::UnwrapVector(cmd::impl::MakeVector( + cmd::WaitUntil([] { return false; }).IgnoringDisable(param)))); + EXPECT_EQ(param, command.RunsWhenDisabled()); +} + +TYPED_TEST_P(MultiCompositionRunsWhenDisabledTest, AllTrue) { + TypeParam command = TypeParam(CommandPtr::UnwrapVector(cmd::impl::MakeVector( + cmd::WaitUntil([] { return false; }).IgnoringDisable(true), + cmd::WaitUntil([] { return false; }).IgnoringDisable(true), + cmd::WaitUntil([] { return false; }).IgnoringDisable(true)))); + EXPECT_EQ(true, command.RunsWhenDisabled()); +} + +TYPED_TEST_P(MultiCompositionRunsWhenDisabledTest, AllFalse) { + TypeParam command = TypeParam(CommandPtr::UnwrapVector(cmd::impl::MakeVector( + cmd::WaitUntil([] { return false; }).IgnoringDisable(false), + cmd::WaitUntil([] { return false; }).IgnoringDisable(false), + cmd::WaitUntil([] { return false; }).IgnoringDisable(false)))); + EXPECT_EQ(false, command.RunsWhenDisabled()); +} + +TYPED_TEST_P(MultiCompositionRunsWhenDisabledTest, TwoTrueOneFalse) { + TypeParam command = TypeParam(CommandPtr::UnwrapVector(cmd::impl::MakeVector( + cmd::WaitUntil([] { return false; }).IgnoringDisable(true), + cmd::WaitUntil([] { return false; }).IgnoringDisable(true), + cmd::WaitUntil([] { return false; }).IgnoringDisable(false)))); + EXPECT_EQ(false, command.RunsWhenDisabled()); +} + +TYPED_TEST_P(MultiCompositionRunsWhenDisabledTest, TwoFalseOneTrue) { + TypeParam command = TypeParam(CommandPtr::UnwrapVector(cmd::impl::MakeVector( + cmd::WaitUntil([] { return false; }).IgnoringDisable(false), + cmd::WaitUntil([] { return false; }).IgnoringDisable(false), + cmd::WaitUntil([] { return false; }).IgnoringDisable(true)))); + EXPECT_EQ(false, command.RunsWhenDisabled()); +} + +REGISTER_TYPED_TEST_SUITE_P(MultiCompositionRunsWhenDisabledTest, OneTrue, + OneFalse, AllTrue, AllFalse, TwoTrueOneFalse, + TwoFalseOneTrue); + +template +class MultiCompositionInterruptibilityTest + : public SingleCompositionInterruptibilityTest {}; + +TYPED_TEST_SUITE_P(MultiCompositionInterruptibilityTest); + +TYPED_TEST_P(MultiCompositionInterruptibilityTest, AllCancelSelf) { + TypeParam command = TypeParam(CommandPtr::UnwrapVector(cmd::impl::MakeVector( + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelSelf), + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelSelf), + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelSelf)))); + EXPECT_EQ(Command::InterruptionBehavior::kCancelSelf, + command.GetInterruptionBehavior()); +} + +TYPED_TEST_P(MultiCompositionInterruptibilityTest, AllCancelIncoming) { + TypeParam command = TypeParam(CommandPtr::UnwrapVector(cmd::impl::MakeVector( + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelIncoming), + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelIncoming), + cmd::WaitUntil([] { return false; }) + .WithInterruptBehavior( + Command::InterruptionBehavior::kCancelIncoming)))); + EXPECT_EQ(Command::InterruptionBehavior::kCancelIncoming, + command.GetInterruptionBehavior()); +} + +TYPED_TEST_P(MultiCompositionInterruptibilityTest, TwoCancelSelfOneIncoming) { + TypeParam command = TypeParam(CommandPtr::UnwrapVector(cmd::impl::MakeVector( + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelSelf), + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelSelf), + cmd::WaitUntil([] { return false; }) + .WithInterruptBehavior( + Command::InterruptionBehavior::kCancelIncoming)))); + EXPECT_EQ(Command::InterruptionBehavior::kCancelSelf, + command.GetInterruptionBehavior()); +} + +TYPED_TEST_P(MultiCompositionInterruptibilityTest, TwoCancelIncomingOneSelf) { + TypeParam command = TypeParam(CommandPtr::UnwrapVector(cmd::impl::MakeVector( + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelIncoming), + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelIncoming), + cmd::WaitUntil([] { + return false; + }).WithInterruptBehavior(Command::InterruptionBehavior::kCancelSelf)))); + EXPECT_EQ(Command::InterruptionBehavior::kCancelSelf, + command.GetInterruptionBehavior()); +} + +REGISTER_TYPED_TEST_SUITE_P(MultiCompositionInterruptibilityTest, AllCancelSelf, + AllCancelIncoming, TwoCancelSelfOneIncoming, + TwoCancelIncomingOneSelf); + +#define INSTANTIATE_MULTI_COMMAND_COMPOSITION_TEST_SUITE(Suite, \ + CompositionType) \ + INSTANTIATE_TYPED_TEST_SUITE_P(Suite, MultiCompositionInterruptibilityTest, \ + CompositionType); \ + INSTANTIATE_TYPED_TEST_SUITE_P(Suite, MultiCompositionRunsWhenDisabledTest, \ + CompositionType); +} // namespace multi +} // namespace frc2 diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelCommandGroupTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelCommandGroupTest.cpp index d6c0295f27..28d498c808 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelCommandGroupTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelCommandGroupTest.cpp @@ -3,6 +3,7 @@ // the WPILib BSD license file in the root directory of this project. #include "CommandTestBase.h" +#include "CompositionTestBase.h" #include "frc2/command/InstantCommand.h" #include "frc2/command/ParallelCommandGroup.h" #include "frc2/command/WaitUntilCommand.h" @@ -115,3 +116,6 @@ TEST_F(ParallelCommandGroupTest, ParallelGroupRequirement) { EXPECT_TRUE(scheduler.IsScheduled(&command3)); EXPECT_FALSE(scheduler.IsScheduled(&group)); } + +INSTANTIATE_MULTI_COMMAND_COMPOSITION_TEST_SUITE(ParallelCommandGroupTest, + ParallelCommandGroup); diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelDeadlineGroupTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelDeadlineGroupTest.cpp index 67d87202bb..4abab336f2 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelDeadlineGroupTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelDeadlineGroupTest.cpp @@ -3,6 +3,7 @@ // the WPILib BSD license file in the root directory of this project. #include "CommandTestBase.h" +#include "CompositionTestBase.h" #include "frc2/command/InstantCommand.h" #include "frc2/command/ParallelDeadlineGroup.h" #include "frc2/command/WaitUntilCommand.h" @@ -131,3 +132,23 @@ TEST_F(ParallelDeadlineGroupTest, ParallelDeadlineRequirement) { EXPECT_TRUE(scheduler.IsScheduled(&command3)); EXPECT_FALSE(scheduler.IsScheduled(&group)); } + +class TestableDeadlineCommand : public ParallelDeadlineGroup { + static ParallelDeadlineGroup ToCommand( + std::vector>&& commands) { + std::vector> vec; + std::unique_ptr deadline = std::move(commands[0]); + for (unsigned int i = 1; i < commands.size(); i++) { + vec.emplace_back(std::move(commands[i])); + } + return ParallelDeadlineGroup(std::move(deadline), std::move(vec)); + } + + public: + explicit TestableDeadlineCommand( + std::vector>&& commands) + : ParallelDeadlineGroup(ToCommand(std::move(commands))) {} +}; + +INSTANTIATE_MULTI_COMMAND_COMPOSITION_TEST_SUITE(ParallelDeadlineGroupTest, + TestableDeadlineCommand); diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelRaceGroupTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelRaceGroupTest.cpp index 72f42747d4..3df2147da8 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelRaceGroupTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/ParallelRaceGroupTest.cpp @@ -3,6 +3,7 @@ // the WPILib BSD license file in the root directory of this project. #include "CommandTestBase.h" +#include "CompositionTestBase.h" #include "frc2/command/InstantCommand.h" #include "frc2/command/ParallelRaceGroup.h" #include "frc2/command/SequentialCommandGroup.h" @@ -202,3 +203,6 @@ TEST_F(ParallelRaceGroupTest, ParallelRaceScheduleTwice) { EXPECT_FALSE(scheduler.IsScheduled(&group)); } + +INSTANTIATE_MULTI_COMMAND_COMPOSITION_TEST_SUITE(ParallelRaceGroupTest, + ParallelRaceGroup); diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/RepeatCommandTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/RepeatCommandTest.cpp index efccf2aca7..b71598314d 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/RepeatCommandTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/RepeatCommandTest.cpp @@ -3,8 +3,9 @@ // the WPILib BSD license file in the root directory of this project. #include "CommandTestBase.h" -#include "frc2/command/Commands.h" +#include "CompositionTestBase.h" #include "frc2/command/FunctionalCommand.h" +#include "frc2/command/RepeatCommand.h" using namespace frc2; class RepeatCommandTest : public CommandTestBase {}; @@ -61,30 +62,5 @@ TEST_F(RepeatCommandTest, CallsMethodsCorrectly) { EXPECT_EQ(1, endCounter); } -class RepeatCommandInterruptibilityTest - : public CommandTestBaseWithParam {}; - -TEST_P(RepeatCommandInterruptibilityTest, Interruptibility) { - CommandPtr command = cmd::WaitUntil([] { return false; }) - .WithInterruptBehavior(GetParam()) - .Repeatedly(); - EXPECT_EQ(GetParam(), command.get()->GetInterruptionBehavior()); -} - -INSTANTIATE_TEST_SUITE_P( - RepeatCommandTests, RepeatCommandInterruptibilityTest, - testing::Values(Command::InterruptionBehavior::kCancelIncoming, - Command::InterruptionBehavior::kCancelSelf)); - -class RepeatCommandRunsWhenDisabledTest - : public CommandTestBaseWithParam {}; - -TEST_P(RepeatCommandRunsWhenDisabledTest, RunsWhenDisabled) { - CommandPtr command = cmd::WaitUntil([] { return false; }) - .IgnoringDisable(GetParam()) - .Repeatedly(); - EXPECT_EQ(GetParam(), command.get()->RunsWhenDisabled()); -} - -INSTANTIATE_TEST_SUITE_P(RepeatCommandTests, RepeatCommandRunsWhenDisabledTest, - testing::Bool()); +INSTANTIATE_SINGLE_COMMAND_COMPOSITION_TEST_SUITE(RepeatCommandTest, + RepeatCommand); diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/SelectCommandTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/SelectCommandTest.cpp index 409e2a6aba..dfea0d336a 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/SelectCommandTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/SelectCommandTest.cpp @@ -3,6 +3,7 @@ // the WPILib BSD license file in the root directory of this project. #include "CommandTestBase.h" +#include "CompositionTestBase.h" #include "frc2/command/ConditionalCommand.h" #include "frc2/command/InstantCommand.h" #include "frc2/command/SelectCommand.h" @@ -57,3 +58,24 @@ TEST_F(SelectCommandTest, SelectCommandRequirement) { EXPECT_TRUE(scheduler.IsScheduled(&command3)); EXPECT_FALSE(scheduler.IsScheduled(&select)); } + +class TestableSelectCommand : public SelectCommand { + static std::vector>> ZipVector( + std::vector>&& commands) { + std::vector>> vec; + int index = 0; + for (auto&& command : commands) { + vec.emplace_back(std::make_pair(index, std::move(command))); + index++; + } + return vec; + } + + public: + explicit TestableSelectCommand( + std::vector>&& commands) + : SelectCommand([] { return 0; }, ZipVector(std::move(commands))) {} +}; + +INSTANTIATE_MULTI_COMMAND_COMPOSITION_TEST_SUITE(SelectCommandTest, + TestableSelectCommand); diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/SequentialCommandGroupTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/SequentialCommandGroupTest.cpp index 2d88c0a752..0048b2416c 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/SequentialCommandGroupTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/SequentialCommandGroupTest.cpp @@ -3,6 +3,7 @@ // the WPILib BSD license file in the root directory of this project. #include "CommandTestBase.h" +#include "CompositionTestBase.h" #include "frc2/command/InstantCommand.h" #include "frc2/command/SequentialCommandGroup.h" #include "frc2/command/WaitUntilCommand.h" @@ -132,3 +133,6 @@ TEST_F(SequentialCommandGroupTest, SequentialGroupRequirement) { EXPECT_TRUE(scheduler.IsScheduled(&command3)); EXPECT_FALSE(scheduler.IsScheduled(&group)); } + +INSTANTIATE_MULTI_COMMAND_COMPOSITION_TEST_SUITE(SequentialCommandGroupTest, + SequentialCommandGroup);