From 59b072c54ad1f349af6c4d8f6684a7232e56b663 Mon Sep 17 00:00:00 2001 From: MEFThunders7035 <95276965+kytpbs@users.noreply.github.com> Date: Mon, 6 May 2024 03:50:46 +0300 Subject: [PATCH 1/8] add Command.repeatedly(int times) to both java and c++ Also has unit tests in it! --- .../wpi/first/wpilibj2/command/Command.java | 22 ++++++++++ .../main/native/cpp/frc2/command/Command.cpp | 4 ++ .../native/cpp/frc2/command/CommandPtr.cpp | 11 +++++ .../native/include/frc2/command/Command.h | 10 +++++ .../native/include/frc2/command/CommandPtr.h | 10 +++++ .../command/CommandDecoratorTest.java | 40 +++++++++++++++++++ .../cpp/frc2/command/CommandDecoratorTest.cpp | 33 +++++++++++++++ 7 files changed, 130 insertions(+) diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java index d6cd4c8860d..9a32bb3335d 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java @@ -401,6 +401,28 @@ public RepeatCommand repeatedly() { return new RepeatCommand(this); } + /** + * Decorates this command to run repeatedly, restarting until the command runs for the given times + * amount. The decorated command can still be canceled. + * + *

This is just syntactic sugar for {@code this.finallyDo(() -> + * counter[0]++).repeatedly().until(() -> counter[0] >= times)} which just means: runs the + * command, then increments the counter, repeatedly until the counter saturates. + * + *

Note: This decorator works by adding this command to a composition. The command the + * decorator was called on cannot be scheduled independently or be added to a different + * composition (namely, decorators), unless it is manually cleared from the list of composed + * commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition + * returned from this method can be further decorated without issue. + * + * @param times the count of times to run the command (inclusively). + * @return the decorated command + */ + public ParallelRaceGroup repeatedly(int times) { + int[] counter = {0}; + return this.finallyDo(() -> counter[0]++).repeatedly().until(() -> counter[0] >= times); + } + /** * Decorates this command to run "by proxy" by wrapping it in a {@link ProxyCommand}. Use this for * "forking off" from command compositions when the user does not wish to extend the command's diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp index af8e30a33a5..bc37be14801 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp @@ -109,6 +109,10 @@ CommandPtr Command::Repeatedly() && { return std::move(*this).ToPtr().Repeatedly(); } +CommandPtr Command::Repeatedly(int times) && { + return std::move(*this).ToPtr().Repeatedly(times); +} + CommandPtr Command::AsProxy() && { return std::move(*this).ToPtr().AsProxy(); } diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp index d4125fdceb8..f017808ac67 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp @@ -50,6 +50,17 @@ CommandPtr CommandPtr::Repeatedly() && { return std::move(*this); } +CommandPtr CommandPtr::Repeatedly(int times) && { + AssertValid(); + std::shared_ptr countPtr = std::make_shared(0); + return std::move(*this) + .FinallyDo([countPtr = countPtr] { (*countPtr)++; }) + .Repeatedly() + .Until([countPtr = countPtr, times = times] { + return ((*countPtr) >= times); + }); +} + CommandPtr CommandPtr::AsProxy() && { AssertValid(); m_ptr = std::make_unique(std::move(m_ptr)); diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/Command.h b/wpilibNewCommands/src/main/native/include/frc2/command/Command.h index 4dea3eb1a5f..dd40b9e24cb 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/Command.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/Command.h @@ -269,6 +269,16 @@ class Command : public wpi::Sendable, public wpi::SendableHelper { [[nodiscard]] CommandPtr Repeatedly() &&; + /** + * Decorates this command to run repeatedly until the given count is reached + * or is interrupted. The decorated command can still be canceled. + * + * @param times the number/count of times to run the command + * @return the decorated command + */ + [[nodiscard]] + CommandPtr Repeatedly(int times) &&; + /** * Decorates this command to run "by proxy" by wrapping it in a ProxyCommand. * Use this for "forking off" from command compositions when the user does not diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h index 81a255a9a73..7bc15c603d0 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h @@ -49,6 +49,16 @@ class CommandPtr final { [[nodiscard]] CommandPtr Repeatedly() &&; + /** + * Decorates this command to run repeatedly until the given count is reached + * or is interrupted. The decorated command can still be canceled. + * + * @param times the number of times to run the command + * @return the decorated command + */ + [[nodiscard]] + CommandPtr Repeatedly(int times) &&; + /** * Decorates this command to run "by proxy" by wrapping it in a ProxyCommand. * Use this for "forking off" from command compositions when the user does not diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java index 4d9ad2c06f9..5c1b5074dbd 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java @@ -420,6 +420,46 @@ void raceWithOrderTest() { } } + @Test + void repeatedlyTest() { + try (CommandScheduler scheduler = new CommandScheduler()) { + AtomicInteger counter = new AtomicInteger(0); + + Command command = new InstantCommand(counter::incrementAndGet); + + Command group = command.repeatedly(); + + scheduler.schedule(group); + for (int i = 1; i <= 50; i++) { + scheduler.run(); + assertEquals(i, counter.get()); + } + + // Should still be scheduled + assertTrue(scheduler.isScheduled(group)); + } + } + + @Test + void repeatForTest() { + try (CommandScheduler scheduler = new CommandScheduler()) { + AtomicInteger counter = new AtomicInteger(0); + + Command command = new InstantCommand(counter::incrementAndGet); + + Command group = command.repeatedly(3); + + scheduler.schedule(group); + for (int i = 0; + scheduler.isScheduled(group); + i++) { // If this causes an infinite loop, repeatedly is cooked + scheduler.run(); + assertEquals(i + 1, counter.get()); + } + assertEquals(3, counter.get()); + } + } + @Test void unlessTest() { try (CommandScheduler scheduler = new CommandScheduler()) { diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp index a0b7726f5d6..edfa7cf9706 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp @@ -383,6 +383,39 @@ TEST_F(CommandDecoratorTest, RaceWithOrder) { EXPECT_TRUE(firstWasPolled); } +TEST_F(CommandDecoratorTest, Repeatedly) { + CommandScheduler scheduler = GetScheduler(); + + int counter = 0; + + auto command = InstantCommand([&counter] { counter++; }, {}).Repeatedly(); + + scheduler.Schedule(command); + + for (int i = 1; i <= 50; i++) { + scheduler.Run(); + EXPECT_EQ(i, counter); + } + + EXPECT_TRUE(scheduler.IsScheduled(command)); +} + +TEST_F(CommandDecoratorTest, RepeatFor) { + CommandScheduler scheduler = GetScheduler(); + + int counter = 0; + + auto command = InstantCommand([&counter] { counter++; }, {}).Repeatedly(3); + + scheduler.Schedule(command); + for (int i = 0; scheduler.IsScheduled(command); i++) { + scheduler.Run(); + EXPECT_EQ(i + 1, counter); + } + + EXPECT_EQ(3, counter); +} + TEST_F(CommandDecoratorTest, Unless) { CommandScheduler scheduler = GetScheduler(); From da6c11b246917ad137fb91aa4e6ddb0bc748cb9f Mon Sep 17 00:00:00 2001 From: Kaya <95276965+kytpbs@users.noreply.github.com> Date: Mon, 27 May 2024 02:58:16 +0300 Subject: [PATCH 2/8] use Atomic Integer instead of array for refrence-passing. --- .../main/java/edu/wpi/first/wpilibj2/command/Command.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java index 9a32bb3335d..fada98a1618 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java @@ -15,6 +15,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BooleanSupplier; /** @@ -419,8 +420,10 @@ public RepeatCommand repeatedly() { * @return the decorated command */ public ParallelRaceGroup repeatedly(int times) { - int[] counter = {0}; - return this.finallyDo(() -> counter[0]++).repeatedly().until(() -> counter[0] >= times); + AtomicInteger counter = new AtomicInteger(0); + return this.finallyDo(counter::getAndIncrement) + .repeatedly() + .until(() -> counter.get() >= times); } /** From eb91b2134586ae5be8aa01aba9f4cb242dfce8d4 Mon Sep 17 00:00:00 2001 From: Kaya <95276965+kytpbs@users.noreply.github.com> Date: Fri, 11 Oct 2024 00:49:47 +0300 Subject: [PATCH 3/8] improve tests so they don't hang when failing also, give better errors Co-Authored-By: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com> --- .../first/wpilibj2/command/CommandDecoratorTest.java | 12 +++++++----- .../native/cpp/frc2/command/CommandDecoratorTest.cpp | 8 ++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java index 5c1b5074dbd..7c5f7abf71f 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java @@ -450,13 +450,15 @@ void repeatForTest() { Command group = command.repeatedly(3); scheduler.schedule(group); - for (int i = 0; - scheduler.isScheduled(group); - i++) { // If this causes an infinite loop, repeatedly is cooked + assertEquals(1, counter.get()); + for (int i = 1; i < 3; i++) { scheduler.run(); - assertEquals(i + 1, counter.get()); + assertEquals(i, counter.get()); + assertTrue(scheduler.isScheduled(group), "Expected group to be scheduled with i = " + i); } - assertEquals(3, counter.get()); + scheduler.run(); + assertEquals(3, counter.get(), "Loop should have run 3 times something went wrong"); + assertFalse(scheduler.isScheduled(group), "This command should have gotten unscheduled"); } } diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp index edfa7cf9706..5355c2e99ac 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp @@ -408,12 +408,16 @@ TEST_F(CommandDecoratorTest, RepeatFor) { auto command = InstantCommand([&counter] { counter++; }, {}).Repeatedly(3); scheduler.Schedule(command); - for (int i = 0; scheduler.IsScheduled(command); i++) { + EXPECT_TRUE(scheduler.IsScheduled(command)); + for (int i = 1; i < 3; i++) { scheduler.Run(); - EXPECT_EQ(i + 1, counter); + EXPECT_EQ(i, counter); + EXPECT_TRUE(scheduler.IsScheduled(command)); } + scheduler.Run(); EXPECT_EQ(3, counter); + EXPECT_FALSE(scheduler.IsScheduled(command)); } TEST_F(CommandDecoratorTest, Unless) { From faf08c2f95c16e27414079d71c05ee90dbb00654 Mon Sep 17 00:00:00 2001 From: Kaya <95276965+kytpbs@users.noreply.github.com> Date: Fri, 11 Oct 2024 00:54:04 +0300 Subject: [PATCH 4/8] use pass by value similar to convention I didn't know you could just pass by value by doing this thx @KangarooKoala for pointing it out. Co-Authored-By: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com> --- .../src/main/native/cpp/frc2/command/CommandPtr.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp index f017808ac67..5bc63f7ffb4 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp @@ -54,11 +54,9 @@ CommandPtr CommandPtr::Repeatedly(int times) && { AssertValid(); std::shared_ptr countPtr = std::make_shared(0); return std::move(*this) - .FinallyDo([countPtr = countPtr] { (*countPtr)++; }) + .FinallyDo([countPtr] { (*countPtr)++; }) .Repeatedly() - .Until([countPtr = countPtr, times = times] { - return ((*countPtr) >= times); - }); + .Until([countPtr, times] { return ((*countPtr) >= times); }); } CommandPtr CommandPtr::AsProxy() && { From 07bb16e4e41a4c9ea51fafaed2c42e5f6ce0c903 Mon Sep 17 00:00:00 2001 From: Kaya <95276965+kytpbs@users.noreply.github.com> Date: Thu, 14 Nov 2024 02:04:20 +0300 Subject: [PATCH 5/8] improve test names --- .../edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java | 2 +- .../src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java index 7c5f7abf71f..31cdca04367 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java @@ -441,7 +441,7 @@ void repeatedlyTest() { } @Test - void repeatForTest() { + void repeatedlyCountTest() { try (CommandScheduler scheduler = new CommandScheduler()) { AtomicInteger counter = new AtomicInteger(0); diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp index 5355c2e99ac..a10d129191b 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp @@ -400,7 +400,7 @@ TEST_F(CommandDecoratorTest, Repeatedly) { EXPECT_TRUE(scheduler.IsScheduled(command)); } -TEST_F(CommandDecoratorTest, RepeatFor) { +TEST_F(CommandDecoratorTest, RepeatedlyCount) { CommandScheduler scheduler = GetScheduler(); int counter = 0; From 9fec4bc1f9f72c74f1309edef64cacf511896d4a Mon Sep 17 00:00:00 2001 From: Kaya <95276965+kytpbs@users.noreply.github.com> Date: Mon, 16 Dec 2024 15:35:40 +0100 Subject: [PATCH 6/8] Better comments and variable names --- .../wpi/first/wpilibj2/command/Command.java | 22 ++++++++----------- .../native/include/frc2/command/CommandPtr.h | 4 ++-- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java index fada98a1618..b9aa08f94b6 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java @@ -15,7 +15,6 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BooleanSupplier; /** @@ -403,12 +402,8 @@ public RepeatCommand repeatedly() { } /** - * Decorates this command to run repeatedly, restarting until the command runs for the given times - * amount. The decorated command can still be canceled. - * - *

This is just syntactic sugar for {@code this.finallyDo(() -> - * counter[0]++).repeatedly().until(() -> counter[0] >= times)} which just means: runs the - * command, then increments the counter, repeatedly until the counter saturates. + * Decorates this command to run repeatedly, restarting until the command runs for the given + * number of times. The decorated command can still be canceled. * *

Note: This decorator works by adding this command to a composition. The command the * decorator was called on cannot be scheduled independently or be added to a different @@ -416,14 +411,15 @@ public RepeatCommand repeatedly() { * commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition * returned from this method can be further decorated without issue. * - * @param times the count of times to run the command (inclusively). + * @param repetitions the count of times to run the command. * @return the decorated command */ - public ParallelRaceGroup repeatedly(int times) { - AtomicInteger counter = new AtomicInteger(0); - return this.finallyDo(counter::getAndIncrement) - .repeatedly() - .until(() -> counter.get() >= times); + public ParallelRaceGroup repeatedly(int repetitions) { + // use an array so that it stays in the heap instead of stack. + // We use an array with a size of 1 instead of `AtomicInteger` because of the performance + // overhead + int[] counter = new int[1]; + return this.finallyDo(() -> counter[0]++).repeatedly().until(() -> counter[0] >= repetitions); } /** diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h index 7bc15c603d0..74d4f457af3 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h @@ -50,8 +50,8 @@ class CommandPtr final { CommandPtr Repeatedly() &&; /** - * Decorates this command to run repeatedly until the given count is reached - * or is interrupted. The decorated command can still be canceled. + * Decorates this command to run repeatedly, restarting until the command runs for the given + * number of times. The decorated command can still be canceled. * * @param times the number of times to run the command * @return the decorated command From f31b58cf22ff9c607970eabf6f80f1a3dd73bd3e Mon Sep 17 00:00:00 2001 From: Kaya <95276965+kytpbs@users.noreply.github.com> Date: Mon, 16 Dec 2024 18:47:09 +0100 Subject: [PATCH 7/8] More explicitly set initial counter value Co-authored-by: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com> --- .../src/main/java/edu/wpi/first/wpilibj2/command/Command.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java index b9aa08f94b6..96563332826 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java @@ -418,7 +418,7 @@ public ParallelRaceGroup repeatedly(int repetitions) { // use an array so that it stays in the heap instead of stack. // We use an array with a size of 1 instead of `AtomicInteger` because of the performance // overhead - int[] counter = new int[1]; + int[] counter = {0}; return this.finallyDo(() -> counter[0]++).repeatedly().until(() -> counter[0] >= repetitions); } From d968cb35b755b5c6deaad1b89be31ba667baf7d4 Mon Sep 17 00:00:00 2001 From: Kaya <95276965+kytpbs@users.noreply.github.com> Date: Sun, 22 Dec 2024 21:17:18 +0300 Subject: [PATCH 8/8] Improve comments & Add failure messages to C++ --- .../main/java/edu/wpi/first/wpilibj2/command/Command.java | 5 ++--- .../src/main/native/include/frc2/command/CommandPtr.h | 4 ++-- .../test/native/cpp/frc2/command/CommandDecoratorTest.cpp | 8 +++++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java index 96563332826..b940bca641d 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java @@ -415,9 +415,8 @@ public RepeatCommand repeatedly() { * @return the decorated command */ public ParallelRaceGroup repeatedly(int repetitions) { - // use an array so that it stays in the heap instead of stack. - // We use an array with a size of 1 instead of `AtomicInteger` because of the performance - // overhead + // Use an array so that it stays in the heap instead of stack. + // We use an array with a size of 1 instead of `AtomicInteger` because of performance difference int[] counter = {0}; return this.finallyDo(() -> counter[0]++).repeatedly().until(() -> counter[0] >= repetitions); } diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h index 74d4f457af3..ae770e15a6e 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h @@ -50,8 +50,8 @@ class CommandPtr final { CommandPtr Repeatedly() &&; /** - * Decorates this command to run repeatedly, restarting until the command runs for the given - * number of times. The decorated command can still be canceled. + * Decorates this command to run repeatedly, restarting until the command runs + * for the given number of times. The decorated command can still be canceled. * * @param times the number of times to run the command * @return the decorated command diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp index a10d129191b..0facb2860a2 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp @@ -412,12 +412,14 @@ TEST_F(CommandDecoratorTest, RepeatedlyCount) { for (int i = 1; i < 3; i++) { scheduler.Run(); EXPECT_EQ(i, counter); - EXPECT_TRUE(scheduler.IsScheduled(command)); + EXPECT_TRUE(scheduler.IsScheduled(command)) + << "Expected group to be scheduled with i = " << i; } scheduler.Run(); - EXPECT_EQ(3, counter); - EXPECT_FALSE(scheduler.IsScheduled(command)); + EXPECT_EQ(3, counter) << "Loop should have run 3 times something went wrong"; + EXPECT_FALSE(scheduler.IsScheduled(command)) + << "This command should have gotten unscheduled"; } TEST_F(CommandDecoratorTest, Unless) {