[sim] Change StepTiming to wait for notifiers (#2603)

Old behavior is available via StepTimingAsync.

This makes it significantly easier to use simulation timing with notifiers.

Also update tests to use simulation framework.  This also speeds up the
timing-dependent tests by using simulation timing.  ResourceLock is used
in the Java tests to prevent parallel execution.

While we're here, tweak HAL Notifier implementation:
- Use wait_for instead of wait_until in WaitForNotifierAlarm
- Check for triggerTime = UINT64_MAX in UpdateNotifierAlarm
This commit is contained in:
Peter Johnson
2020-09-27 13:27:53 -07:00
committed by GitHub
parent 62731bea20
commit c3b3fb8b74
23 changed files with 278 additions and 185 deletions

View File

@@ -8,15 +8,20 @@
package edu.wpi.first.wpilibj2.command;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.simulation.SimHooks;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class CommandDecoratorTest extends CommandTestBase {
@Test
@ResourceLock("timing")
void withTimeoutTest() {
HAL.initialize(500, 0);
SimHooks.pauseTiming();
try (CommandScheduler scheduler = new CommandScheduler()) {
Command command1 = new WaitCommand(10);
@@ -28,10 +33,12 @@ class CommandDecoratorTest extends CommandTestBase {
assertFalse(scheduler.isScheduled(command1));
assertTrue(scheduler.isScheduled(timeout));
Timer.delay(3);
SimHooks.stepTiming(3);
scheduler.run();
assertFalse(scheduler.isScheduled(timeout));
} finally {
SimHooks.resumeTiming();
}
}

View File

@@ -9,10 +9,12 @@ package edu.wpi.first.wpilibj2.command;
import java.util.ArrayList;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.controller.PIDController;
import edu.wpi.first.wpilibj.controller.ProfiledPIDController;
@@ -31,13 +33,14 @@ import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
class MecanumControllerCommandTest {
@BeforeAll
static void setupAll() {
@BeforeEach
void setupAll() {
HAL.initialize(500, 0);
SimHooks.pauseTiming();
}
@AfterAll
static void cleanupAll() {
@AfterEach
void cleanupAll() {
SimHooks.resumeTiming();
}
@@ -86,6 +89,7 @@ class MecanumControllerCommandTest {
}
@Test
@ResourceLock("timing")
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
void testReachesReference() {
final var subsystem = new Subsystem() {};

View File

@@ -7,17 +7,30 @@
package edu.wpi.first.wpilibj2.command;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.parallel.ResourceLock;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.simulation.SimHooks;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
@DisabledOnOs(OS.MAC)
class NotifierCommandTest extends CommandTestBase {
@BeforeEach
void setup() {
HAL.initialize(500, 0);
SimHooks.pauseTiming();
}
@AfterEach
void cleanup() {
SimHooks.resumeTiming();
}
@Test
@ResourceLock("timing")
void notifierCommandScheduleTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
Counter counter = new Counter();
@@ -25,11 +38,12 @@ class NotifierCommandTest extends CommandTestBase {
NotifierCommand command = new NotifierCommand(counter::increment, 0.01);
scheduler.schedule(command);
Timer.delay(0.25);
for (int i = 0; i < 5; ++i) {
SimHooks.stepTiming(0.005);
}
scheduler.cancel(command);
assertTrue(counter.m_counter > 10, "Should have hit at least 10 triggers");
assertTrue(counter.m_counter < 100, "Shouldn't hit more then 100 triggers");
assertEquals(2, counter.m_counter);
}
}
}

View File

@@ -9,10 +9,12 @@ package edu.wpi.first.wpilibj2.command;
import java.util.ArrayList;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.controller.PIDController;
import edu.wpi.first.wpilibj.controller.ProfiledPIDController;
@@ -31,13 +33,14 @@ import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
class SwerveControllerCommandTest {
@BeforeAll
static void setupAll() {
@BeforeEach
void setup() {
HAL.initialize(500, 0);
SimHooks.pauseTiming();
}
@AfterAll
static void cleanupAll() {
@AfterEach
void cleanup() {
SimHooks.resumeTiming();
}
@@ -80,6 +83,7 @@ class SwerveControllerCommandTest {
}
@Test
@ResourceLock("timing")
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
void testReachesReference() {
final var subsystem = new Subsystem() {};

View File

@@ -7,9 +7,13 @@
package edu.wpi.first.wpilibj2.command;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.simulation.SimHooks;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -19,19 +23,31 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class WaitCommandTest extends CommandTestBase {
@BeforeEach
void setup() {
HAL.initialize(500, 0);
SimHooks.pauseTiming();
}
@AfterEach
void cleanup() {
SimHooks.resumeTiming();
}
@Test
@ResourceLock("timing")
void waitCommandTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
WaitCommand waitCommand = new WaitCommand(2);
scheduler.schedule(waitCommand);
scheduler.run();
Timer.delay(1);
SimHooks.stepTiming(1);
scheduler.run();
assertTrue(scheduler.isScheduled(waitCommand));
Timer.delay(2);
SimHooks.stepTiming(2);
scheduler.run();
@@ -40,6 +56,7 @@ class WaitCommandTest extends CommandTestBase {
}
@Test
@ResourceLock("timing")
void withTimeoutTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
MockCommandHolder command1Holder = new MockCommandHolder(true);
@@ -56,7 +73,7 @@ class WaitCommandTest extends CommandTestBase {
assertFalse(scheduler.isScheduled(command1));
assertTrue(scheduler.isScheduled(timeout));
Timer.delay(3);
SimHooks.stepTiming(3);
scheduler.run();
verify(command1).end(true);