Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cmd] Add missing C++ decorators #6599

Merged
merged 2 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,19 @@ CommandPtr Command::BeforeStarting(std::function<void()> toRun,
requirements);
}

CommandPtr Command::BeforeStarting(CommandPtr&& before) && {
return std::move(*this).ToPtr().BeforeStarting(std::move(before));
}

CommandPtr Command::AndThen(std::function<void()> toRun,
Requirements requirements) && {
return std::move(*this).ToPtr().AndThen(std::move(toRun), requirements);
}

CommandPtr Command::AndThen(CommandPtr&& next) && {
return std::move(*this).ToPtr().AndThen(std::move(next));
}

CommandPtr Command::Repeatedly() && {
return std::move(*this).ToPtr().Repeatedly();
}
Expand All @@ -120,6 +128,18 @@ CommandPtr Command::OnlyIf(std::function<bool()> condition) && {
return std::move(*this).ToPtr().OnlyIf(std::move(condition));
}

CommandPtr Command::DeadlineFor(CommandPtr&& parallel) && {
return std::move(*this).ToPtr().DeadlineFor(std::move(parallel));
}

CommandPtr Command::AlongWith(CommandPtr&& parallel) && {
return std::move(*this).ToPtr().AlongWith(std::move(parallel));
}

CommandPtr Command::RaceWith(CommandPtr&& parallel) && {
return std::move(*this).ToPtr().RaceWith(std::move(parallel));
}

CommandPtr Command::FinallyDo(std::function<void(bool)> end) && {
return std::move(*this).ToPtr().FinallyDo(std::move(end));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,16 @@ class Command : public wpi::Sendable, public wpi::SendableHelper<Command> {
CommandPtr BeforeStarting(std::function<void()> toRun,
Requirements requirements = {}) &&;

/**
* Decorates this command with another command to run before this command
* starts.
*
* @param before the command to run before this one
* @return the decorated command
*/
[[nodiscard]]
CommandPtr BeforeStarting(CommandPtr&& before) &&;

/**
* Decorates this command with a runnable to run after the command finishes.
*
Expand All @@ -239,6 +249,17 @@ class Command : public wpi::Sendable, public wpi::SendableHelper<Command> {
CommandPtr AndThen(std::function<void()> toRun,
Requirements requirements = {}) &&;

/**
* Decorates this command with a set of commands to run after it in sequence.
* Often more convenient/less-verbose than constructing a
* SequentialCommandGroup explicitly.
*
* @param next the commands to run next
* @return the decorated command
*/
[[nodiscard]]
CommandPtr AndThen(CommandPtr&& next) &&;

/**
* Decorates this command to run repeatedly, restarting it when it ends, until
* this command is interrupted. The decorated command can still be canceled.
Expand Down Expand Up @@ -288,6 +309,40 @@ class Command : public wpi::Sendable, public wpi::SendableHelper<Command> {
[[nodiscard]]
CommandPtr OnlyIf(std::function<bool()> condition) &&;

/**
* Decorates this command with a set of commands to run parallel to it, ending
* when the calling command ends and interrupting all the others. Often more
* convenient/less-verbose than constructing a new {@link
* ParallelDeadlineGroup} explicitly.
*
* @param parallel the commands to run in parallel. Note the parallel commands
* will be interupted when the deadline command ends
* @return the decorated command
*/
[[nodiscard]]
CommandPtr DeadlineFor(CommandPtr&& parallel) &&;
/**
* Decorates this command with a set of commands to run parallel to it, ending
* when the last command ends. Often more convenient/less-verbose than
* constructing a new {@link ParallelCommandGroup} explicitly.
*
* @param parallel the commands to run in parallel
* @return the decorated command
*/
[[nodiscard]]
CommandPtr AlongWith(CommandPtr&& parallel) &&;

/**
* Decorates this command with a set of commands to run parallel to it, ending
* when the first command ends. Often more convenient/less-verbose than
* constructing a new {@link ParallelRaceGroup} explicitly.
*
* @param parallel the commands to run in parallel
* @return the decorated command
*/
[[nodiscard]]
CommandPtr RaceWith(CommandPtr&& parallel) &&;

/**
* Decorates this command to run or stop when disabled.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,14 @@ void withTimeoutTest() {
HAL.initialize(500, 0);
SimHooks.pauseTiming();
try (CommandScheduler scheduler = new CommandScheduler()) {
Command command1 = new WaitCommand(10);

Command timeout = command1.withTimeout(2);
Command timeout = new RunCommand(() -> {}).withTimeout(0.1);

scheduler.schedule(timeout);
scheduler.run();

assertFalse(scheduler.isScheduled(command1));
Starlight220 marked this conversation as resolved.
Show resolved Hide resolved
assertTrue(scheduler.isScheduled(timeout));

SimHooks.stepTiming(3);
SimHooks.stepTiming(0.15);
scheduler.run();

assertFalse(scheduler.isScheduled(timeout));
Expand All @@ -44,31 +41,37 @@ void withTimeoutTest() {
@Test
void untilTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
AtomicBoolean condition = new AtomicBoolean();
AtomicBoolean finish = new AtomicBoolean();

Command command = new WaitCommand(10).until(condition::get);
Command command = new RunCommand(() -> {}).until(finish::get);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these instances of RunCommand(() -> {}) can be replaced with Commands.idle().

Not important enough to block this PR, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened #6652 since there's a bunch of other spots in command tests that should also be updated. If this PR gets merged before the issue gets resolved, I'll update the list on the issue, and if the issue gets resolved first, then I'll update this PR.


scheduler.schedule(command);
scheduler.run();

assertTrue(scheduler.isScheduled(command));
condition.set(true);

finish.set(true);
scheduler.run();

assertFalse(scheduler.isScheduled(command));
}
}

@Test
void onlyWhileTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
AtomicBoolean condition = new AtomicBoolean(true);
AtomicBoolean run = new AtomicBoolean(true);

Command command = new WaitCommand(10).onlyWhile(condition::get);
Command command = new RunCommand(() -> {}).onlyWhile(run::get);

scheduler.schedule(command);
scheduler.run();

assertTrue(scheduler.isScheduled(command));
condition.set(false);

run.set(false);
scheduler.run();

assertFalse(scheduler.isScheduled(command));
}
}
Expand All @@ -90,61 +93,75 @@ void ignoringDisableTest() {
@Test
void beforeStartingTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
AtomicBoolean condition = new AtomicBoolean();
condition.set(false);
AtomicBoolean finished = new AtomicBoolean();
finished.set(false);

Command command = new InstantCommand().beforeStarting(() -> finished.set(true));

Command command = new InstantCommand();
scheduler.schedule(command);

scheduler.schedule(command.beforeStarting(() -> condition.set(true)));
assertTrue(finished.get());

assertTrue(condition.get());
scheduler.run();

assertTrue(scheduler.isScheduled(command));

scheduler.run();

assertFalse(scheduler.isScheduled(command));
}
}

@Test
void andThenLambdaTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
AtomicBoolean condition = new AtomicBoolean();
condition.set(false);
AtomicBoolean finished = new AtomicBoolean(false);

Command command = new InstantCommand();
Command command = new InstantCommand().andThen(() -> finished.set(true));

scheduler.schedule(command.andThen(() -> condition.set(true)));
scheduler.schedule(command);

assertFalse(condition.get());
assertFalse(finished.get());

scheduler.run();

assertTrue(condition.get());
assertTrue(finished.get());

scheduler.run();

assertFalse(scheduler.isScheduled(command));
}
}

@Test
void andThenTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
AtomicBoolean condition = new AtomicBoolean();
condition.set(false);
AtomicBoolean condition = new AtomicBoolean(false);

Command command1 = new InstantCommand();
Command command2 = new InstantCommand(() -> condition.set(true));
Command group = command1.andThen(command2);

scheduler.schedule(command1.andThen(command2));
scheduler.schedule(group);

assertFalse(condition.get());

scheduler.run();

assertTrue(condition.get());

scheduler.run();

assertFalse(scheduler.isScheduled(group));
Starlight220 marked this conversation as resolved.
Show resolved Hide resolved
}
}

@Test
void deadlineWithTest() {
void deadlineForTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
AtomicBoolean condition = new AtomicBoolean();
condition.set(false);
AtomicBoolean finish = new AtomicBoolean(false);

Command dictator = new WaitUntilCommand(condition::get);
Command dictator = new WaitUntilCommand(finish::get);
Command endsBefore = new InstantCommand();
Command endsAfter = new WaitUntilCommand(() -> false);

Expand All @@ -155,7 +172,7 @@ void deadlineWithTest() {

assertTrue(scheduler.isScheduled(group));

condition.set(true);
finish.set(true);
scheduler.run();

assertFalse(scheduler.isScheduled(group));
Expand All @@ -165,10 +182,9 @@ void deadlineWithTest() {
@Test
void alongWithTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
AtomicBoolean condition = new AtomicBoolean();
condition.set(false);
AtomicBoolean finish = new AtomicBoolean(false);

Command command1 = new WaitUntilCommand(condition::get);
Command command1 = new WaitUntilCommand(finish::get);
Command command2 = new InstantCommand();

Command group = command1.alongWith(command2);
Expand All @@ -178,7 +194,7 @@ void alongWithTest() {

assertTrue(scheduler.isScheduled(group));

condition.set(true);
finish.set(true);
scheduler.run();

assertFalse(scheduler.isScheduled(group));
Expand All @@ -203,40 +219,38 @@ void raceWithTest() {
@Test
void unlessTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
AtomicBoolean hasRun = new AtomicBoolean(false);
AtomicBoolean unlessCondition = new AtomicBoolean(true);
AtomicBoolean hasRunCondition = new AtomicBoolean(false);

Command command =
new InstantCommand(() -> hasRunCondition.set(true)).unless(unlessCondition::get);
Command command = new InstantCommand(() -> hasRun.set(true)).unless(unlessCondition::get);

scheduler.schedule(command);
scheduler.run();
assertFalse(hasRunCondition.get());
assertFalse(hasRun.get());

unlessCondition.set(false);
scheduler.schedule(command);
scheduler.run();
assertTrue(hasRunCondition.get());
assertTrue(hasRun.get());
}
}

@Test
void onlyIfTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
AtomicBoolean hasRun = new AtomicBoolean(false);
AtomicBoolean onlyIfCondition = new AtomicBoolean(false);
AtomicBoolean hasRunCondition = new AtomicBoolean(false);

Command command =
new InstantCommand(() -> hasRunCondition.set(true)).onlyIf(onlyIfCondition::get);
Command command = new InstantCommand(() -> hasRun.set(true)).onlyIf(onlyIfCondition::get);

scheduler.schedule(command);
scheduler.run();
assertFalse(hasRunCondition.get());
assertFalse(hasRun.get());

onlyIfCondition.set(true);
scheduler.schedule(command);
scheduler.run();
assertTrue(hasRunCondition.get());
assertTrue(hasRun.get());
}
}

Expand Down
Loading
Loading