From 47cb693907ee22515ce820e2112f55dfe0df30ce Mon Sep 17 00:00:00 2001 From: Ryan Cahoon Date: Tue, 1 Oct 2024 04:54:00 -0700 Subject: [PATCH] Revisions to Status system --- .vscode/settings.json | 2 + .../com/team766/framework3/Conditions.java | 87 +++++++++++++------ .../FunctionalInstantProcedure.java | 4 +- .../framework3/FunctionalProcedure.java | 4 +- .../team766/framework3/InstantProcedure.java | 2 +- .../com/team766/framework3/Mechanism.java | 23 +++-- .../com/team766/framework3/Procedure.java | 14 +-- .../java/com/team766/framework3/Request.java | 7 +- .../java/com/team766/framework3/Rule.java | 14 +-- .../com/team766/framework3/RuleEngine.java | 6 +- .../team766/framework3/SensorMechanism.java | 38 ++++++++ .../com/team766/framework3/StatusBus.java | 66 +++++++++----- .../framework3/WPILibCommandProcedure.java | 6 +- src/main/java/com/team766/library/Holder.java | 19 ++++ .../com/team766/framework3/FakeMechanism.java | 15 ++-- .../com/team766/framework3/FakeProcedure.java | 4 +- .../com/team766/framework3/MechanismTest.java | 27 +++--- .../java/com/team766/framework3/RuleTest.java | 4 +- 18 files changed, 238 insertions(+), 104 deletions(-) create mode 100644 src/main/java/com/team766/framework3/SensorMechanism.java create mode 100644 src/main/java/com/team766/library/Holder.java diff --git a/.vscode/settings.json b/.vscode/settings.json index f25587d5b..c07977ca2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -35,7 +35,9 @@ "java.checkstyle.configuration": "${workspaceFolder}/.github/linters/checkstyle.xml", "java.checkstyle.version": "9.3", "java.completion.favoriteStaticMembers": [ + "com.team766.framework3.Conditions.*", "com.team766.framework3.RulePersistence.*", + "com.team766.framework3.StatusBus.*", "org.junit.Assert.*", "org.junit.Assume.*", "org.junit.jupiter.api.Assertions.*", diff --git a/src/main/java/com/team766/framework3/Conditions.java b/src/main/java/com/team766/framework3/Conditions.java index 923023d0b..4b6ffde7c 100644 --- a/src/main/java/com/team766/framework3/Conditions.java +++ b/src/main/java/com/team766/framework3/Conditions.java @@ -1,47 +1,84 @@ package com.team766.framework3; +import com.team766.library.Holder; +import java.util.Optional; import java.util.function.BooleanSupplier; +import java.util.function.Predicate; +import java.util.function.Supplier; /** * Pre-canned Conditions used frqeuently in robot programming. */ public class Conditions { + public static T waitFor(Context context, Supplier> supplier) { + final Holder result = new Holder<>(); + context.waitFor( + () -> { + final var t = supplier.get(); + t.ifPresent(result::set); + return t.isPresent(); + }); + return result.value; + } + + public static Optional waitForValueOrTimeout( + Context context, Supplier> supplier, double timeoutSeconds) { + final Holder> result = new Holder<>(Optional.empty()); + context.waitForConditionOrTimeout( + () -> { + result.value = supplier.get(); + return result.value.isPresent(); + }, + timeoutSeconds); + return result.value; + } + + public static boolean checkForStatus(Class statusClass) { + return StatusBus.getStatusEntry(statusClass).isPresent(); + } /** * Predicate that checks whether or not the latest {@link Status} passes the - * check provided by {@link Checker}. + * check provided by {@code predicate}. */ - public static class StatusCheck implements BooleanSupplier { + public static boolean checkForStatusWith( + Class statusClass, Predicate predicate) { + return StatusBus.getStatusValue(statusClass, predicate::test).orElse(false); + } - /** Functional interface for checking whether or not a {@link Status} passes desired criteria. */ - @FunctionalInterface - public interface Checker { - boolean check(S status); - } + public static boolean checkForStatusEntryWith( + Class statusClass, Predicate> predicate) { + return StatusBus.getStatusEntry(statusClass).map(predicate::test).orElse(false); + } - private final Class clazz; - private final Checker checker; + public static T waitForStatus(Context context, Class statusClass) { + return waitFor(context, () -> StatusBus.getStatus(statusClass)); + } - public StatusCheck(Class clazz, Checker checker) { - this.clazz = clazz; - this.checker = checker; - } + public static Optional waitForStatusOrTimeout( + Context context, Class statusClass, double timeoutSeconds) { + return waitForValueOrTimeout( + context, () -> StatusBus.getStatus(statusClass), timeoutSeconds); + } - public boolean getAsBoolean() { - S status = StatusBus.getInstance().getStatus(clazz); - return checker.check(status); - } + public static T waitForStatus( + Context context, Class statusClass, Predicate predicate) { + return waitFor(context, () -> StatusBus.getStatus(statusClass).filter(predicate)); } - /** - * Predicate that checks if the provided {@link Request} has been fulfilled by checking - * the latest {@link Status}. - */ - public static class AwaitRequest extends StatusCheck { + public static Optional waitForStatusOrTimeout( + Context context, Class statusClass, Predicate predicate, double timeoutSeconds) { + return waitForValueOrTimeout( + context, () -> StatusBus.getStatus(statusClass).filter(predicate), timeoutSeconds); + } - public AwaitRequest(Class clazz, Request request) { - super(clazz, request::isDone); - } + public static void waitForRequest(Context context, Request request) { + context.waitFor(request::isDone); + } + + public static void waitForRequestOrTimeout( + Context context, Request request, double timeoutSeconds) { + context.waitForConditionOrTimeout(request::isDone, timeoutSeconds); } /** diff --git a/src/main/java/com/team766/framework3/FunctionalInstantProcedure.java b/src/main/java/com/team766/framework3/FunctionalInstantProcedure.java index 131369f2e..d9eebf7ac 100644 --- a/src/main/java/com/team766/framework3/FunctionalInstantProcedure.java +++ b/src/main/java/com/team766/framework3/FunctionalInstantProcedure.java @@ -5,12 +5,12 @@ public final class FunctionalInstantProcedure extends InstantProcedure { private final Runnable runnable; - public FunctionalInstantProcedure(Set> reservations, Runnable runnable) { + public FunctionalInstantProcedure(Set> reservations, Runnable runnable) { this(runnable.toString(), reservations, runnable); } public FunctionalInstantProcedure( - String name, Set> reservations, Runnable runnable) { + String name, Set> reservations, Runnable runnable) { super(name, reservations); this.runnable = runnable; } diff --git a/src/main/java/com/team766/framework3/FunctionalProcedure.java b/src/main/java/com/team766/framework3/FunctionalProcedure.java index 141c416ce..2c0c9a111 100644 --- a/src/main/java/com/team766/framework3/FunctionalProcedure.java +++ b/src/main/java/com/team766/framework3/FunctionalProcedure.java @@ -6,12 +6,12 @@ public final class FunctionalProcedure extends Procedure { private final Consumer runnable; - public FunctionalProcedure(Set> reservations, Consumer runnable) { + public FunctionalProcedure(Set> reservations, Consumer runnable) { this(runnable.toString(), reservations, runnable); } public FunctionalProcedure( - String name, Set> reservations, Consumer runnable) { + String name, Set> reservations, Consumer runnable) { super(name, reservations); this.runnable = runnable; } diff --git a/src/main/java/com/team766/framework3/InstantProcedure.java b/src/main/java/com/team766/framework3/InstantProcedure.java index bb3be2bfe..b1406c56a 100644 --- a/src/main/java/com/team766/framework3/InstantProcedure.java +++ b/src/main/java/com/team766/framework3/InstantProcedure.java @@ -8,7 +8,7 @@ protected InstantProcedure() { super(); } - protected InstantProcedure(String name, Set> reservations) { + protected InstantProcedure(String name, Set> reservations) { super(name, reservations); } diff --git a/src/main/java/com/team766/framework3/Mechanism.java b/src/main/java/com/team766/framework3/Mechanism.java index 68df73446..199bf7ceb 100644 --- a/src/main/java/com/team766/framework3/Mechanism.java +++ b/src/main/java/com/team766/framework3/Mechanism.java @@ -8,18 +8,21 @@ import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.SubsystemBase; import java.util.ArrayList; +import java.util.NoSuchElementException; import java.util.Objects; -public abstract class Mechanism> extends SubsystemBase implements LoggingBase { +public abstract class Mechanism extends SubsystemBase + implements LoggingBase { private Thread m_runningPeriodic = null; - private Mechanism superstructure = null; + private Mechanism superstructure = null; // If this Mechanism is a superstructure, this is a list of its constituent Mechanisms. - private ArrayList> submechanisms = new ArrayList<>(); + private ArrayList> submechanisms = new ArrayList<>(); private R request = null; private boolean isRequestNew = false; + private S status = null; /** * This Command runs when no other Command (i.e. Procedure) is reserving this Mechanism. @@ -72,7 +75,7 @@ public Category getLoggerCategory() { * * @param superstructure The superstructure this Mechanism is part of. */ - public void setSuperstructure(Mechanism superstructure) { + public void setSuperstructure(Mechanism superstructure) { Objects.requireNonNull(superstructure); if (this.superstructure != null) { throw new IllegalStateException("Mechanism is already part of a superstructure"); @@ -143,6 +146,13 @@ protected void checkContextReservation() { ReservingCommand.checkCurrentCommandHasReservation(this); } + public S getMechanismStatus() { + if (status == null) { + throw new NoSuchElementException(getName() + " has not published a status yet"); + } + return status; + } + @Override public final void periodic() { super.periodic(); @@ -166,7 +176,8 @@ private void periodicInternal() { } boolean wasRequestNew = isRequestNew; isRequestNew = false; - run(request, wasRequestNew); + status = run(request, wasRequestNew); + StatusBus.publishStatus(status); } catch (Exception ex) { ex.printStackTrace(); LoggerExceptionUtils.logException(ex); @@ -175,5 +186,5 @@ private void periodicInternal() { } } - protected abstract void run(R request, boolean isRequestNew); + protected abstract S run(R request, boolean isRequestNew); } diff --git a/src/main/java/com/team766/framework3/Procedure.java b/src/main/java/com/team766/framework3/Procedure.java index 92fdc12f7..db8dcd6f4 100644 --- a/src/main/java/com/team766/framework3/Procedure.java +++ b/src/main/java/com/team766/framework3/Procedure.java @@ -22,19 +22,19 @@ private static synchronized int createNewId() { } private final String name; - private final Set> reservations; + private final Set> reservations; protected Procedure() { this.name = createName(); this.reservations = Sets.newHashSet(); } - protected Procedure(Set> reservations) { + protected Procedure(Set> reservations) { this.name = createName(); this.reservations = reservations; } - protected Procedure(String name, Set> reservations) { + protected Procedure(String name, Set> reservations) { this.name = name; this.reservations = reservations; } @@ -59,22 +59,22 @@ public Category getLoggerCategory() { return Category.PROCEDURES; } - protected final > M reserve(M m) { + protected final > M reserve(M m) { reservations.add(m); return m; } - protected final void reserve(Mechanism... ms) { + protected final void reserve(Mechanism... ms) { for (var m : ms) { reservations.add(m); } } - protected final void reserve(Collection> ms) { + protected final void reserve(Collection> ms) { reservations.addAll(ms); } - public final Set> reservations() { + public final Set> reservations() { return reservations; } diff --git a/src/main/java/com/team766/framework3/Request.java b/src/main/java/com/team766/framework3/Request.java index 3ed39b085..1b2f777d7 100644 --- a/src/main/java/com/team766/framework3/Request.java +++ b/src/main/java/com/team766/framework3/Request.java @@ -9,13 +9,12 @@ * * Each Mechanism will have its own implementation of the {@link Request} marker interface. */ -public interface Request { +public interface Request { /** - * Checks whether or not this request has been fulfilled, via the supplied {@link Status}. This - * {@link Status} should be the latest one retrieved via {@link StatusBus#getStatus(Class)}. + * Checks whether or not this request has been fulfilled. */ - boolean isDone(S status); + boolean isDone(); // TODO(MF3): do we need any way of checking if the request has been bumped/canceled? } diff --git a/src/main/java/com/team766/framework3/Rule.java b/src/main/java/com/team766/framework3/Rule.java index 0469743d8..750a41932 100644 --- a/src/main/java/com/team766/framework3/Rule.java +++ b/src/main/java/com/team766/framework3/Rule.java @@ -132,7 +132,9 @@ public Builder withOnTriggeringProcedure( /** Specify a creator for the Procedure that should be run when this rule starts triggering. */ public Builder withOnTriggeringProcedure( - RulePersistence rulePersistence, Set> reservations, Runnable action) { + RulePersistence rulePersistence, + Set> reservations, + Runnable action) { applyRulePersistence( rulePersistence, () -> new FunctionalInstantProcedure(reservations, action)); return this; @@ -141,7 +143,7 @@ public Builder withOnTriggeringProcedure( /** Specify a creator for the Procedure that should be run when this rule starts triggering. */ public Builder withOnTriggeringProcedure( RulePersistence rulePersistence, - Set> reservations, + Set> reservations, Consumer action) { applyRulePersistence( rulePersistence, () -> new FunctionalProcedure(reservations, action)); @@ -156,7 +158,7 @@ public Builder withFinishedTriggeringProcedure(Supplier action) { /** Specify a creator for the Procedure that should be run when this rule was triggering before and is no longer triggering. */ public Builder withFinishedTriggeringProcedure( - Set> reservations, Runnable action) { + Set> reservations, Runnable action) { this.finishedTriggeringProcedure = () -> new FunctionalInstantProcedure(reservations, action); return this; @@ -221,7 +223,7 @@ protected List build(BooleanSupplier parentPredicate) { private final BooleanSupplier predicate; private final Map> triggerProcedures = Maps.newEnumMap(TriggerType.class); - private final Map>> triggerReservations = + private final Map>> triggerReservations = Maps.newEnumMap(TriggerType.class); private final Map triggerCancellation = Maps.newEnumMap(TriggerType.class); @@ -263,7 +265,7 @@ private Rule( } } - private static Set> getReservationsForProcedure(Supplier supplier) { + private static Set> getReservationsForProcedure(Supplier supplier) { if (supplier != null) { Procedure procedure = supplier.get(); if (procedure != null) { @@ -314,7 +316,7 @@ public String getName() { } } - /* package */ Set> getMechanismsToReserve() { + /* package */ Set> getMechanismsToReserve() { if (triggerReservations.containsKey(currentTriggerType)) { return triggerReservations.get(currentTriggerType); } diff --git a/src/main/java/com/team766/framework3/RuleEngine.java b/src/main/java/com/team766/framework3/RuleEngine.java index 9943e0481..8f1d03f23 100644 --- a/src/main/java/com/team766/framework3/RuleEngine.java +++ b/src/main/java/com/team766/framework3/RuleEngine.java @@ -75,7 +75,7 @@ protected Rule getRuleForTriggeredProcedure(Command command) { } public final void run() { - Set> mechanismsToUse = new HashSet<>(); + Set> mechanismsToUse = new HashSet<>(); // TODO(MF3): when creating a Procedure, check that the reservations are the same as // what the Rule pre-computed. @@ -94,9 +94,9 @@ public final void run() { int priority = getPriorityForRule(rule); // see if there are mechanisms a potential procedure would want to reserve - Set> reservations = rule.getMechanismsToReserve(); + Set> reservations = rule.getMechanismsToReserve(); log(Severity.INFO, "Rule " + rule.getName() + " would reserve " + reservations); - for (Mechanism mechanism : reservations) { + for (Mechanism mechanism : reservations) { // see if any of the mechanisms higher priority rules will use would also be // used by this lower priority rule's procedure. if (mechanismsToUse.contains(mechanism)) { diff --git a/src/main/java/com/team766/framework3/SensorMechanism.java b/src/main/java/com/team766/framework3/SensorMechanism.java new file mode 100644 index 000000000..ceff7797b --- /dev/null +++ b/src/main/java/com/team766/framework3/SensorMechanism.java @@ -0,0 +1,38 @@ +package com.team766.framework3; + +import com.team766.logging.Category; +import com.team766.logging.LoggerExceptionUtils; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import java.util.NoSuchElementException; + +public abstract class SensorMechanism extends SubsystemBase + implements LoggingBase { + private S status = null; + + @Override + public Category getLoggerCategory() { + return Category.MECHANISMS; + } + + public S getStatus() { + if (status == null) { + throw new NoSuchElementException(getName() + " has not published a status yet"); + } + return status; + } + + @Override + public final void periodic() { + super.periodic(); + + try { + status = run(); + StatusBus.publishStatus(status); + } catch (Exception ex) { + ex.printStackTrace(); + LoggerExceptionUtils.logException(ex); + } + } + + protected abstract S run(); +} diff --git a/src/main/java/com/team766/framework3/StatusBus.java b/src/main/java/com/team766/framework3/StatusBus.java index 9bf9ae779..f0b9872d1 100644 --- a/src/main/java/com/team766/framework3/StatusBus.java +++ b/src/main/java/com/team766/framework3/StatusBus.java @@ -1,30 +1,32 @@ package com.team766.framework3; +import com.team766.hal.RobotProvider; import com.team766.logging.Category; +import com.team766.logging.Logger; +import com.team766.logging.Severity; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Optional; +import java.util.function.Function; /** * Bus for broadcasting and querying {@link Status} of different parts of the robot (eg state of a Mechanism). - * This is a Singleton, accessed via {@link #getInstance()}. Producers can call {@link #publish} to publish - * their latest {@link Status}. Consumers can call {@link #getStatus(Class)} with the class Object - * (eg, {@code MyStatus.class}) for the {@link Status} they are interested in querying, to get the latest - * published {@link Status}. + * This is a Singleton. Producers can call {@link #publish} to publish their latest {@link Status}. + * Consumers can call {@link #getStatus(Class)} with the class Object (eg, {@code MyStatus.class}) + * for the {@link Status} they are interested in querying, to get the latest published {@link Status}. */ -public class StatusBus implements LoggingBase { +public class StatusBus { - private static StatusBus s_instance = new StatusBus(); - private final Map, Status> statuses = new LinkedHashMap<>(); - - /** - * Get the Singleton instance of the {@link StatusBus}. - */ - public static StatusBus getInstance() { - return s_instance; + public record Entry(T status, double timestamp) { + public double age() { + return RobotProvider.instance.getClock().getTime() - timestamp; + } } - // TODO: would this be helpful? - // private void clear() { + private static final Map, Entry> statuses = new LinkedHashMap<>(); + + // TODO(MF3): would this be helpful? + // private static void clear() { // statuses.clear(); // } @@ -34,10 +36,18 @@ public static StatusBus getInstance() { * * This method also logs the Status to diagnostic logs. */ - public void publish(Status status) { - statuses.put(status.getClass(), status); - // TODO: also publish to data logs - log("StatusBus received Status (" + status.getClass().getName() + "): " + status); + public static void publishStatus(S status) { + statuses.put( + status.getClass(), + new Entry<>(status, RobotProvider.instance.getClock().getTime())); + // TODO(MF3): also publish to data logs + Logger.get(Category.FRAMEWORK) + .logRaw( + Severity.INFO, + "StatusBus received Status (" + + status.getClass().getName() + + "): " + + status); } /** @@ -50,12 +60,20 @@ public void publish(Status status) { * @return The latest published {@link Status} or null if the {@link Status} hasn't been published. */ @SuppressWarnings("unchecked") - public S getStatus(Class statusClass) { - return (S) statuses.get(statusClass); + public static Optional> getStatusEntry(Class statusClass) { + return Optional.ofNullable((Entry) statuses.get(statusClass)); + } + + public static Optional getStatus(Class statusClass) { + return getStatusEntry(statusClass).map(Entry::status); + } + + public static S getStatusOrThrow(Class statusClass) { + return getStatus(statusClass).orElseThrow(); } - @Override - public Category getLoggerCategory() { - return Category.FRAMEWORK; + public static Optional getStatusValue( + Class statusClass, Function getter) { + return getStatusEntry(statusClass).map(s -> getter.apply(s.status())); } } diff --git a/src/main/java/com/team766/framework3/WPILibCommandProcedure.java b/src/main/java/com/team766/framework3/WPILibCommandProcedure.java index f10dbf8f8..6f67c1d55 100644 --- a/src/main/java/com/team766/framework3/WPILibCommandProcedure.java +++ b/src/main/java/com/team766/framework3/WPILibCommandProcedure.java @@ -21,14 +21,14 @@ public WPILibCommandProcedure(final Command command) { } @SuppressWarnings("unchecked") - private static Set> checkSubsystemsAreMechanisms(Set requirements) { + private static Set> checkSubsystemsAreMechanisms(Set requirements) { for (var s : requirements) { - if (!(s instanceof Mechanism)) { + if (!(s instanceof Mechanism)) { throw new IllegalArgumentException( "Maroon Framework requires the use of Mechanism instead of Subsystem"); } } - return (Set>) (Set) requirements; + return (Set>) (Set) requirements; } @Override diff --git a/src/main/java/com/team766/library/Holder.java b/src/main/java/com/team766/library/Holder.java new file mode 100644 index 000000000..fb78551c5 --- /dev/null +++ b/src/main/java/com/team766/library/Holder.java @@ -0,0 +1,19 @@ +package com.team766.library; + +public class Holder { + public T value; + + public Holder() {} + + public Holder(T value) { + this.value = value; + } + + public T get() { + return value; + } + + public void set(T value) { + this.value = value; + } +} diff --git a/src/test/java/com/team766/framework3/FakeMechanism.java b/src/test/java/com/team766/framework3/FakeMechanism.java index f53d06073..bafb02212 100644 --- a/src/test/java/com/team766/framework3/FakeMechanism.java +++ b/src/test/java/com/team766/framework3/FakeMechanism.java @@ -1,12 +1,14 @@ package com.team766.framework3; -class FakeMechanism extends Mechanism { - record FakeStatus(int currentState) implements Status {} +import static com.team766.framework3.Conditions.checkForStatusWith; - public record FakeRequest(int targetState) implements Request { +class FakeMechanism extends Mechanism { + public record FakeStatus(int currentState) implements Status {} + + public record FakeRequest(int targetState) implements Request { @Override - public boolean isDone(FakeStatus status) { - return status.currentState() == targetState; + public boolean isDone() { + return checkForStatusWith(FakeStatus.class, s -> s.currentState() == targetState); } } @@ -19,9 +21,10 @@ protected FakeRequest getInitialRequest() { } @Override - protected void run(FakeRequest request, boolean isRequestNew) { + protected FakeStatus run(FakeRequest request, boolean isRequestNew) { currentRequest = request; wasRequestNew = isRequestNew; + return new FakeStatus(request.targetState()); } } diff --git a/src/test/java/com/team766/framework3/FakeProcedure.java b/src/test/java/com/team766/framework3/FakeProcedure.java index 617d1a204..fb33a298e 100644 --- a/src/test/java/com/team766/framework3/FakeProcedure.java +++ b/src/test/java/com/team766/framework3/FakeProcedure.java @@ -7,12 +7,12 @@ class FakeProcedure extends Procedure { private int age = 0; private boolean ended = false; - public FakeProcedure(int lifetime, Set> reservations) { + public FakeProcedure(int lifetime, Set> reservations) { super(reservations); this.lifetime = lifetime; } - public FakeProcedure(String name, int lifetime, Set> reservations) { + public FakeProcedure(String name, int lifetime, Set> reservations) { super(name, reservations); this.lifetime = lifetime; } diff --git a/src/test/java/com/team766/framework3/MechanismTest.java b/src/test/java/com/team766/framework3/MechanismTest.java index 1b82b47f8..a3a10c50b 100644 --- a/src/test/java/com/team766/framework3/MechanismTest.java +++ b/src/test/java/com/team766/framework3/MechanismTest.java @@ -5,6 +5,7 @@ import com.team766.TestCase3; import com.team766.framework3.FakeMechanism.FakeRequest; +import com.team766.framework3.FakeMechanism.FakeStatus; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Test; @@ -71,14 +72,16 @@ public void testRequests() { /// not reserved the Mechanism. @Test public void testFailedCheckContextReservationInProcedure() { - class DummyMechanism extends Mechanism { + class DummyMechanism extends Mechanism { @Override protected FakeRequest getInitialRequest() { return new FakeRequest(-1); } @Override - protected void run(FakeRequest request, boolean isRequestNew) {} + protected FakeStatus run(FakeRequest request, boolean isRequestNew) { + return new FakeStatus(request.targetState()); + } } var mech = new DummyMechanism(); @@ -116,12 +119,13 @@ public void testCheckContextReservationInRun() { var mech = new FakeMechanism() { @Override - protected void run(FakeRequest request, boolean isRequestNew) { + protected FakeStatus run(FakeRequest request, boolean isRequestNew) { try { checkContextReservation(); } catch (Throwable ex) { thrownException.set(ex); } + return new FakeStatus(request.targetState()); } }; step(); @@ -196,7 +200,7 @@ protected FakeRequest getIdleRequest() { /// Test making a Mechanism part of a superstructure. @Test public void testSuperstructure() { - class Superstructure extends Mechanism { + class Superstructure extends Mechanism { // NOTE: Real superstructures should have their members be private. This is public // to test handling of bad code patterns, and to allow us to inspect the state of the // inner mechanism for purposes of testing the framework. @@ -213,14 +217,15 @@ protected FakeRequest getInitialRequest() { } @Override - protected void run(FakeRequest request, boolean isRequestNew) { - if (!isRequestNew) return; - - if (request.targetState() == 0) { - submechanism.setRequest(new FakeRequest(2)); - } else { - submechanism.setRequest(new FakeRequest(4)); + protected FakeStatus run(FakeRequest request, boolean isRequestNew) { + if (isRequestNew) { + if (request.targetState() == 0) { + submechanism.setRequest(new FakeRequest(2)); + } else { + submechanism.setRequest(new FakeRequest(4)); + } } + return new FakeStatus(request.targetState()); } } var superstructure = new Superstructure(); diff --git a/src/test/java/com/team766/framework3/RuleTest.java b/src/test/java/com/team766/framework3/RuleTest.java index c731db24c..926a26ba0 100644 --- a/src/test/java/com/team766/framework3/RuleTest.java +++ b/src/test/java/com/team766/framework3/RuleTest.java @@ -94,9 +94,9 @@ public void testEvaluate() { @Test public void testGetMechanismsToReserve() { - final Set> newlyMechanisms = + final Set> newlyMechanisms = Set.of(new FakeMechanism1(), new FakeMechanism2()); - final Set> finishedMechanisms = Set.of(new FakeMechanism()); + final Set> finishedMechanisms = Set.of(new FakeMechanism()); Rule duckDuckGooseGoose = getSingleElement(