test(javaTest): require all history tasks to complete
This commit is contained in:
@@ -90,26 +90,33 @@ public final class HistoricalDispatchSimulator {
|
|||||||
clearanceMoves, executions, terminal, planner, assignment, plc,
|
clearanceMoves, executions, terminal, planner, assignment, plc,
|
||||||
reservations, events);
|
reservations, events);
|
||||||
Set<String> traversedEdges = new LinkedHashSet<String>();
|
Set<String> traversedEdges = new LinkedHashSet<String>();
|
||||||
advanceClearanceMoves(tick, now, input, config, vehicles, clearanceMoves,
|
ClearanceProgress clearanceProgress = advanceClearanceMoves(
|
||||||
|
tick, now, input, config, vehicles, clearanceMoves,
|
||||||
ledger, plc, events, traversedEdges);
|
ledger, plc, events, traversedEdges);
|
||||||
advanceActiveTasks(tick, now, input, config, queue, vehicles,
|
boolean businessProgress = advanceActiveTasks(
|
||||||
|
tick, now, input, config, queue, vehicles,
|
||||||
active, executions, terminal, planner, ledger, plc, archive, wms,
|
active, executions, terminal, planner, ledger, plc, archive, wms,
|
||||||
invariants, reservations, clearanceMoves, clearancePlanner,
|
invariants, reservations, clearanceMoves, clearancePlanner,
|
||||||
events, traversedEdges);
|
events, traversedEdges);
|
||||||
verifyLedger(ledger, invariants);
|
verifyLedger(ledger, invariants);
|
||||||
|
|
||||||
if (watchdog.observe(terminal.size())) {
|
if (watchdog.observe(terminal.size(),
|
||||||
|
businessProgress || clearanceProgress.moved,
|
||||||
|
clearanceProgress.completed)) {
|
||||||
invariants.deadlock();
|
invariants.deadlock();
|
||||||
snapshotWaiting(queue, active, executions, terminal, plc,
|
throw new IllegalStateException("simulation made no physical progress at tick "
|
||||||
"DEADLOCK_TIMEOUT", now);
|
+ tick + ", terminal=" + terminal.size()
|
||||||
break;
|
+ ", queued=" + queue.size() + ", active=" + active.keySet()
|
||||||
|
+ ", clearance=" + clearanceMoves.keySet());
|
||||||
}
|
}
|
||||||
now += STEP_MILLIS;
|
now += STEP_MILLIS;
|
||||||
tick++;
|
tick++;
|
||||||
}
|
}
|
||||||
if (terminal.size() < expected) {
|
if (terminal.size() < expected) {
|
||||||
snapshotWaiting(queue, active, executions, terminal, plc,
|
throw new IllegalStateException("simulation tick limit reached: tick=" + tick
|
||||||
"TICK_LIMIT", now);
|
+ ", terminal=" + terminal.size() + ", expected=" + expected
|
||||||
|
+ ", queued=" + queue.size() + ", active=" + active.keySet()
|
||||||
|
+ ", clearance=" + clearanceMoves.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<SimulationTaskResult> results = new ArrayList<SimulationTaskResult>(terminal.values());
|
List<SimulationTaskResult> results = new ArrayList<SimulationTaskResult>(terminal.values());
|
||||||
@@ -212,7 +219,6 @@ public final class HistoricalDispatchSimulator {
|
|||||||
terminal.put(task.getSimulationTaskId(), result(executions.get(
|
terminal.put(task.getSimulationTaskId(), result(executions.get(
|
||||||
task.getSimulationTaskId()), SimulationTaskStatus.FAILED,
|
task.getSimulationTaskId()), SimulationTaskStatus.FAILED,
|
||||||
"NO_ROUTE", plc, now));
|
"NO_ROUTE", plc, now));
|
||||||
progress = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,7 +404,6 @@ public final class HistoricalDispatchSimulator {
|
|||||||
current.execution.task.getSimulationTaskId(), vehicleId,
|
current.execution.task.getSimulationTaskId(), vehicleId,
|
||||||
"RETRY_EXHAUSTED_REDISPATCH", from, to));
|
"RETRY_EXHAUSTED_REDISPATCH", from, to));
|
||||||
}
|
}
|
||||||
progress = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Site nextSite = input.getGridMap().getSite(to);
|
Site nextSite = input.getGridMap().getSite(to);
|
||||||
@@ -421,7 +426,7 @@ public final class HistoricalDispatchSimulator {
|
|||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void advanceClearanceMoves(long tick, long now,
|
private ClearanceProgress advanceClearanceMoves(long tick, long now,
|
||||||
HistoricalSimulationInput input,
|
HistoricalSimulationInput input,
|
||||||
SimulationConfig config,
|
SimulationConfig config,
|
||||||
Map<String, SimulatedVehicleRuntime> vehicles,
|
Map<String, SimulatedVehicleRuntime> vehicles,
|
||||||
@@ -430,6 +435,8 @@ public final class HistoricalDispatchSimulator {
|
|||||||
SimulatedPlcGateway plc,
|
SimulatedPlcGateway plc,
|
||||||
List<SimulationTickEvent> events,
|
List<SimulationTickEvent> events,
|
||||||
Set<String> traversedEdges) {
|
Set<String> traversedEdges) {
|
||||||
|
boolean moved = false;
|
||||||
|
boolean completed = false;
|
||||||
List<String> vehicleIds = new ArrayList<String>(clearanceMoves.keySet());
|
List<String> vehicleIds = new ArrayList<String>(clearanceMoves.keySet());
|
||||||
Collections.sort(vehicleIds);
|
Collections.sort(vehicleIds);
|
||||||
for (String vehicleId : vehicleIds) {
|
for (String vehicleId : vehicleIds) {
|
||||||
@@ -495,15 +502,18 @@ public final class HistoricalDispatchSimulator {
|
|||||||
ledger.release(vehicleId, Arrays.asList(ResourceKey.node(from), edge));
|
ledger.release(vehicleId, Arrays.asList(ResourceKey.node(from), edge));
|
||||||
traversedEdges.add(direction);
|
traversedEdges.add(direction);
|
||||||
clearance.moved();
|
clearance.moved();
|
||||||
|
moved = true;
|
||||||
events.add(event(tick, now, "CLEARANCE_MOVE", clearance.getOwnerTaskId(),
|
events.add(event(tick, now, "CLEARANCE_MOVE", clearance.getOwnerTaskId(),
|
||||||
vehicleId, "ACK", from, to));
|
vehicleId, "ACK", from, to));
|
||||||
if (clearance.isComplete()) {
|
if (clearance.isComplete()) {
|
||||||
clearanceMoves.remove(vehicleId);
|
clearanceMoves.remove(vehicleId);
|
||||||
|
completed = true;
|
||||||
events.add(event(tick, now, "CLEARANCE_COMPLETE",
|
events.add(event(tick, now, "CLEARANCE_COMPLETE",
|
||||||
clearance.getOwnerTaskId(), vehicleId, "ROUTE_CLEARED",
|
clearance.getOwnerTaskId(), vehicleId, "ROUTE_CLEARED",
|
||||||
to, to));
|
to, to));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new ClearanceProgress(moved, completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean planClearanceForIdleBlockers(
|
private boolean planClearanceForIdleBlockers(
|
||||||
@@ -714,4 +724,14 @@ public final class HistoricalDispatchSimulator {
|
|||||||
this.route = Collections.unmodifiableList(new ArrayList<String>(route));
|
this.route = Collections.unmodifiableList(new ArrayList<String>(route));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class ClearanceProgress {
|
||||||
|
private final boolean moved;
|
||||||
|
private final boolean completed;
|
||||||
|
|
||||||
|
private ClearanceProgress(boolean moved, boolean completed) {
|
||||||
|
this.moved = moved;
|
||||||
|
this.completed = completed;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,15 @@ public final class SimulationProgressWatchdog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean observe(int terminalCount) {
|
public boolean observe(int terminalCount) {
|
||||||
|
return observe(terminalCount, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean observe(int terminalCount, boolean vehicleMoved,
|
||||||
|
boolean clearanceCompleted) {
|
||||||
if (terminalCount < lastTerminalCount) {
|
if (terminalCount < lastTerminalCount) {
|
||||||
throw new IllegalArgumentException("terminal count must be monotonic");
|
throw new IllegalArgumentException("terminal count must be monotonic");
|
||||||
}
|
}
|
||||||
if (terminalCount > lastTerminalCount) {
|
if (terminalCount > lastTerminalCount || vehicleMoved || clearanceCompleted) {
|
||||||
lastTerminalCount = terminalCount;
|
lastTerminalCount = terminalCount;
|
||||||
unchangedEvents = 0;
|
unchangedEvents = 0;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -18,12 +18,14 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||||||
class HistoricalDispatchSimulationRealDataTest {
|
class HistoricalDispatchSimulationRealDataTest {
|
||||||
private static HistoricalDispatchSimulationResult result;
|
private static HistoricalDispatchSimulationResult result;
|
||||||
private static HistoricalDispatchSimulationResult secondRun;
|
private static HistoricalDispatchSimulationResult secondRun;
|
||||||
|
private static HistoricalSimulationInput simulationInput;
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void simulateRealHistoryTwice() {
|
static void simulateRealHistoryTwice() {
|
||||||
HistoricalQueueDataset dataset = new HistoricalQueueLoader().load(
|
HistoricalQueueDataset dataset = new HistoricalQueueLoader().load(
|
||||||
HistoricalDispatchSimulationRealDataTest.class.getClassLoader(), "shadow/history");
|
HistoricalDispatchSimulationRealDataTest.class.getClassLoader(), "shadow/history");
|
||||||
HistoricalSimulationInput input = new HistoricalSimulationInputFactory().create(dataset);
|
HistoricalSimulationInput input = new HistoricalSimulationInputFactory().create(dataset);
|
||||||
|
simulationInput = input;
|
||||||
DeterministicFaultPlan.Builder faults = DeterministicFaultPlan.builder();
|
DeterministicFaultPlan.Builder faults = DeterministicFaultPlan.builder();
|
||||||
for (int i = 0; i < input.getTasks().size(); i += 37) {
|
for (int i = 0; i < input.getTasks().size(); i += 37) {
|
||||||
faults.plcFailure(input.getTasks().get(i).getSimulationTaskId(), 1, SEND_FAILURE);
|
faults.plcFailure(input.getTasks().get(i).getSimulationTaskId(), 1, SEND_FAILURE);
|
||||||
@@ -46,22 +48,30 @@ class HistoricalDispatchSimulationRealDataTest {
|
|||||||
assertNotNull(task.getRecord().getTaskNo());
|
assertNotNull(task.getRecord().getTaskNo());
|
||||||
assertNotNull(task.getRecord().getStartSite());
|
assertNotNull(task.getRecord().getStartSite());
|
||||||
assertNotNull(task.getRecord().getEndSite());
|
assertNotNull(task.getRecord().getEndSite());
|
||||||
|
for (int i = 1; i < task.getPlannedPath().size(); i++) {
|
||||||
|
assertTrue(simulationInput.getGridMap()
|
||||||
|
.getNeighbors(task.getPlannedPath().get(i - 1))
|
||||||
|
.contains(task.getPlannedPath().get(i)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void completesTheRealWorkloadDeterministicallyWithoutSafetyViolations() {
|
void completesTheRealWorkloadDeterministicallyWithoutSafetyViolations() {
|
||||||
assertEquals(240, result.getTaskResults().size());
|
assertEquals(240, result.getTaskResults().size());
|
||||||
assertEquals(240, result.getCompletedCount()
|
assertEquals(240, result.getCompletedCount());
|
||||||
+ result.getWaitingCount() + result.getFailedCount());
|
assertEquals(0, result.getWaitingCount());
|
||||||
assertTrue(result.getCompletedCount() > 0);
|
assertEquals(0, result.getFailedCount());
|
||||||
if (result.getWaitingCount() > 0) {
|
|
||||||
assertTrue(result.getInvariants().getDeadlocks() > 0);
|
|
||||||
}
|
|
||||||
assertTrue(result.getReassignmentCount() > 0);
|
assertTrue(result.getReassignmentCount() > 0);
|
||||||
assertTrue(result.getRetryCount() > 0);
|
assertTrue(result.getRetryCount() > 0);
|
||||||
assertEquals(result.getCompletedCount(), result.getArchiveCount());
|
assertEquals(240, result.getArchiveCount());
|
||||||
assertEquals(result.getCompletedCount(), result.getWmsBusinessEffects());
|
assertEquals(240, result.getWmsBusinessEffects());
|
||||||
assertEquals(result.getCompletedCount() * 2, result.getWmsDeliveryAttempts());
|
assertEquals(480, result.getWmsDeliveryAttempts());
|
||||||
|
assertEquals(0, result.getInvariants().getDeadlocks());
|
||||||
|
assertEquals(0, result.getInvariants().getCapacityViolations());
|
||||||
|
assertEquals(0, result.getInvariants().getNodeDoubleOccupancyViolations());
|
||||||
|
assertEquals(0, result.getInvariants().getOppositeEdgeViolations());
|
||||||
|
assertEquals(0, result.getInvariants().getDuplicateArchiveAttempts());
|
||||||
|
assertEquals(0, result.getInvariants().getDuplicateWmsBusinessEffects());
|
||||||
assertEquals(0, result.getInvariants().totalSafetyViolations());
|
assertEquals(0, result.getInvariants().totalSafetyViolations());
|
||||||
assertEquals(result.canonicalView(), secondRun.canonicalView());
|
assertEquals(result.canonicalView(), secondRun.canonicalView());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,4 +24,20 @@ class SimulationProgressWatchdogTest {
|
|||||||
assertFalse(watchdog.observe(1));
|
assertFalse(watchdog.observe(1));
|
||||||
assertTrue(watchdog.observe(1));
|
assertTrue(watchdog.observe(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void resetsOnlyForTerminalMovementOrCompletedClearanceProgress() {
|
||||||
|
SimulationProgressWatchdog watchdog = new SimulationProgressWatchdog(3, 0);
|
||||||
|
|
||||||
|
assertFalse(watchdog.observe(0, false, false));
|
||||||
|
assertFalse(watchdog.observe(0, false, false));
|
||||||
|
assertFalse(watchdog.observe(0, true, false));
|
||||||
|
assertFalse(watchdog.observe(0, false, false));
|
||||||
|
assertFalse(watchdog.observe(0, false, true));
|
||||||
|
assertFalse(watchdog.observe(0, false, false));
|
||||||
|
assertFalse(watchdog.observe(1, false, false));
|
||||||
|
assertFalse(watchdog.observe(1, false, false));
|
||||||
|
assertFalse(watchdog.observe(1, false, false));
|
||||||
|
assertTrue(watchdog.observe(1, false, false));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user