[commands] Fix compose-while-scheduled issue and test all compositions (#5581)

This commit is contained in:
Ryan Blue
2023-12-23 15:12:13 -05:00
committed by GitHub
parent aeb1a4aa33
commit ef1cb3f41e
20 changed files with 146 additions and 83 deletions

View File

@@ -1,47 +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.
package edu.wpi.first.wpilibj2.command;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
class CommandGroupErrorTest extends CommandTestBase {
@Test
void commandInMultipleGroupsTest() {
MockCommandHolder command1Holder = new MockCommandHolder(true);
Command command1 = command1Holder.getMock();
MockCommandHolder command2Holder = new MockCommandHolder(true);
Command command2 = command2Holder.getMock();
new ParallelCommandGroup(command1, command2);
assertThrows(
IllegalArgumentException.class, () -> new ParallelCommandGroup(command1, command2));
}
@Test
void commandInGroupExternallyScheduledTest() {
MockCommandHolder command1Holder = new MockCommandHolder(true);
Command command1 = command1Holder.getMock();
MockCommandHolder command2Holder = new MockCommandHolder(true);
Command command2 = command2Holder.getMock();
new ParallelCommandGroup(command1, command2);
assertThrows(
IllegalArgumentException.class, () -> CommandScheduler.getInstance().schedule(command1));
}
@Test
void redecoratedCommandErrorTest() {
Command command = new InstantCommand();
assertDoesNotThrow(() -> command.withTimeout(10).until(() -> false));
assertThrows(IllegalArgumentException.class, () -> command.withTimeout(10));
CommandScheduler.getInstance().removeComposedCommand(command);
assertDoesNotThrow(() -> command.withTimeout(10));
}
}

View File

@@ -13,11 +13,11 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
interface MultiCompositionTestBase<T extends Command> extends SingleCompositionTestBase<T> {
T compose(Command... members);
abstract class MultiCompositionTestBase<T extends Command> extends SingleCompositionTestBase<T> {
abstract T compose(Command... members);
@Override
default T composeSingle(Command member) {
T composeSingle(Command member) {
return compose(member);
}
@@ -63,7 +63,7 @@ interface MultiCompositionTestBase<T extends Command> extends SingleCompositionT
@MethodSource
@ParameterizedTest(name = "interruptible[{index}]: {0}")
default void interruptible(
void interruptible(
@SuppressWarnings("unused") String name,
InterruptionBehavior expected,
Command command1,
@@ -103,7 +103,7 @@ interface MultiCompositionTestBase<T extends Command> extends SingleCompositionT
@MethodSource
@ParameterizedTest(name = "runsWhenDisabled[{index}]: {0}")
default void runsWhenDisabled(
void runsWhenDisabled(
@SuppressWarnings("unused") String name,
boolean expected,
Command command1,

View File

@@ -14,8 +14,7 @@ import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.Test;
class ParallelCommandGroupTest extends CommandTestBase
implements MultiCompositionTestBase<ParallelCommandGroup> {
class ParallelCommandGroupTest extends MultiCompositionTestBase<ParallelCommandGroup> {
@Test
void parallelGroupScheduleTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {

View File

@@ -14,8 +14,7 @@ import static org.mockito.internal.verification.VerificationModeFactory.times;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
class ParallelDeadlineGroupTest extends CommandTestBase
implements MultiCompositionTestBase<ParallelDeadlineGroup> {
class ParallelDeadlineGroupTest extends MultiCompositionTestBase<ParallelDeadlineGroup> {
@Test
void parallelDeadlineScheduleTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {

View File

@@ -16,8 +16,7 @@ import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.Test;
class ParallelRaceGroupTest extends CommandTestBase
implements MultiCompositionTestBase<ParallelRaceGroup> {
class ParallelRaceGroupTest extends MultiCompositionTestBase<ParallelRaceGroup> {
@Test
void parallelRaceScheduleTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {

View File

@@ -10,8 +10,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
class RepeatCommandTest extends CommandTestBase
implements SingleCompositionTestBase<RepeatCommand> {
class RepeatCommandTest extends SingleCompositionTestBase<RepeatCommand> {
@Test
void callsMethodsCorrectly() {
try (CommandScheduler scheduler = new CommandScheduler()) {

View File

@@ -13,8 +13,7 @@ import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
class SelectCommandTest extends CommandTestBase
implements MultiCompositionTestBase<SelectCommand<Integer>> {
class SelectCommandTest extends MultiCompositionTestBase<SelectCommand<Integer>> {
@Test
void selectCommandTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {

View File

@@ -12,8 +12,7 @@ import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.Test;
class SequentialCommandGroupTest extends CommandTestBase
implements MultiCompositionTestBase<SequentialCommandGroup> {
class SequentialCommandGroupTest extends MultiCompositionTestBase<SequentialCommandGroup> {
@Test
void sequentialGroupScheduleTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {

View File

@@ -5,17 +5,19 @@
package edu.wpi.first.wpilibj2.command;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
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;
public interface SingleCompositionTestBase<T extends Command> {
T composeSingle(Command member);
public abstract class SingleCompositionTestBase<T extends Command> extends CommandTestBase {
abstract T composeSingle(Command member);
@EnumSource(Command.InterruptionBehavior.class)
@ParameterizedTest
default void interruptible(Command.InterruptionBehavior interruptionBehavior) {
void interruptible(Command.InterruptionBehavior interruptionBehavior) {
var command =
composeSingle(
new WaitUntilCommand(() -> false).withInterruptBehavior(interruptionBehavior));
@@ -24,9 +26,38 @@ public interface SingleCompositionTestBase<T extends Command> {
@ValueSource(booleans = {true, false})
@ParameterizedTest
default void runWhenDisabled(boolean runsWhenDisabled) {
void runWhenDisabled(boolean runsWhenDisabled) {
var command =
composeSingle(new WaitUntilCommand(() -> false).ignoringDisable(runsWhenDisabled));
assertEquals(runsWhenDisabled, command.runsWhenDisabled());
}
@Test
void commandInOtherCompositionTest() {
var command = new InstantCommand();
new WrapperCommand(command) {};
assertThrows(IllegalArgumentException.class, () -> composeSingle(command));
}
@Test
void commandInMultipleCompositionsTest() {
var command = new InstantCommand();
composeSingle(command);
assertThrows(IllegalArgumentException.class, () -> composeSingle(command));
}
@Test
void composeThenScheduleTest() {
var command = new InstantCommand();
composeSingle(command);
assertThrows(
IllegalArgumentException.class, () -> CommandScheduler.getInstance().schedule(command));
}
@Test
void scheduleThenComposeTest() {
var command = new RunCommand(() -> {});
CommandScheduler.getInstance().schedule(command);
assertThrows(IllegalArgumentException.class, () -> composeSingle(command));
}
}