From a834803efbb8ad0050292708ce27e34bf2f987c6 Mon Sep 17 00:00:00 2001 From: maillard Date: Fri, 27 Oct 2023 11:44:06 -0700 Subject: [PATCH 1/5] Add serializer/deserializers for Controllable duration parameters --- .../generator/MissionModelGenerator.java | 86 ++++++++++++++----- .../merlin/protocol/model/SchedulerModel.java | 4 + 2 files changed, 68 insertions(+), 22 deletions(-) diff --git a/merlin-framework-processor/src/main/java/gov/nasa/jpl/aerie/merlin/processor/generator/MissionModelGenerator.java b/merlin-framework-processor/src/main/java/gov/nasa/jpl/aerie/merlin/processor/generator/MissionModelGenerator.java index 1ef819cb83..be17603c33 100644 --- a/merlin-framework-processor/src/main/java/gov/nasa/jpl/aerie/merlin/processor/generator/MissionModelGenerator.java +++ b/merlin-framework-processor/src/main/java/gov/nasa/jpl/aerie/merlin/processor/generator/MissionModelGenerator.java @@ -259,7 +259,7 @@ private static CodeBlock generateMissionModelInstantiation(final MissionModelRec /** Generate `GeneratedSchedulerModel` class. */ public JavaFile generateSchedulerModel(final MissionModelRecord missionModel) { final var typeName = missionModel.getSchedulerModelName(); - + final var durationValueMapperCodeBlock = generateDurationMapperBlock(missionModel); final var typeSpec = TypeSpec .classBuilder(typeName) @@ -301,6 +301,33 @@ public JavaFile generateSchedulerModel(final MissionModelRecord missionModel) { .orElse(CodeBlock.builder()).build()) .addStatement("return result") .build()) + .addMethod(MethodSpec + .methodBuilder("serializeDuration") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .returns(SerializedValue.class) + .addParameter( + TypeName.get(Duration.class), + "duration", + Modifier.FINAL) + .addStatement( + "return $L.serializeValue(duration)", durationValueMapperCodeBlock.get() + ) + .build()) + .addMethod(MethodSpec + .methodBuilder("deserializeDuration") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .addParameter( + TypeName.get(SerializedValue.class), + "serializedDuration", + Modifier.FINAL) + .addStatement( + "return $L.deserializeValue(serializedDuration).getSuccessOrThrow()", durationValueMapperCodeBlock.get() + ) + .returns(Duration.class) + .build()) + .build(); return JavaFile @@ -551,13 +578,14 @@ public JavaFile generateActivityTypes(final MissionModelRecord missionModel) { private record ComputedAttributesCodeBlocks(TypeName typeName, FieldSpec fieldDef) {} /** Generate an `InputType` implementation. */ - public Optional generateInputType(final MissionModelRecord missionModel, final InputTypeRecord inputType, final String name) { + public Optional generateInputType(final MissionModelRecord missionModel, + final InputTypeRecord inputType, + final String name) { final var mapperBlocks$ = generateParameterMapperBlocks(missionModel, inputType); if (mapperBlocks$.isEmpty()) return Optional.empty(); final var mapperBlocks = mapperBlocks$.get(); final var mapperMethodMaker = MapperMethodMaker.make(inputType); - return Optional.of(TypeSpec .classBuilder(name) // The location of the missionModel package determines where to put this class. @@ -576,16 +604,16 @@ public Optional generateInputType(final MissionModelRecord missionMode .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addFields( inputType.parameters() - .stream() - .map(parameter -> FieldSpec - .builder( - ParameterizedTypeName.get( - ClassName.get(gov.nasa.jpl.aerie.merlin.framework.ValueMapper.class), - TypeName.get(parameter.type).box()), - "mapper_" + parameter.name) - .addModifiers(Modifier.PRIVATE, Modifier.FINAL) - .build()) - .collect(Collectors.toList())) + .stream() + .map(parameter -> FieldSpec + .builder( + ParameterizedTypeName.get( + ClassName.get(gov.nasa.jpl.aerie.merlin.framework.ValueMapper.class), + TypeName.get(parameter.type).box()), + "mapper_" + parameter.name) + .addModifiers(Modifier.PRIVATE, Modifier.FINAL) + .build()) + .collect(Collectors.toList())) .addMethod( MethodSpec .constructorBuilder() @@ -600,15 +628,15 @@ public Optional generateInputType(final MissionModelRecord missionMode .build()) .addCode( inputType.parameters() - .stream() - .map(parameter -> CodeBlock - .builder() - .addStatement( - "this.mapper_$L =\n$L", - parameter.name, - mapperBlocks.get(parameter.name))) - .reduce(CodeBlock.builder(), (x, y) -> x.add(y.build())) - .build()) + .stream() + .map(parameter -> CodeBlock + .builder() + .addStatement( + "this.mapper_$L =\n$L", + parameter.name, + mapperBlocks.get(parameter.name))) + .reduce(CodeBlock.builder(), (x, y) -> x.add(y.build())) + .build()) .build()) .addMethod(mapperMethodMaker.makeGetRequiredParametersMethod()) .addMethod(mapperMethodMaker.makeGetParametersMethod()) @@ -868,4 +896,18 @@ private Optional> generateParameterMapperBlocks(final Mis return failed ? Optional.empty() : Optional.of(mapperBlocks); } + + private Optional generateDurationMapperBlock(final MissionModelRecord missionModel){ + final var resolver = new Resolver(this.typeUtils, this.elementUtils, missionModel.typeRules()); + final var mapperBlock = resolver.instantiateNullableMapperFor( + elementUtils.getTypeElement(Duration.class.getName()).asType()); + if (mapperBlock.isPresent()) { + return mapperBlock; + } else { + messager.printMessage( + Diagnostic.Kind.ERROR, + "Failed to generate value mapper for Duration"); + return Optional.empty(); + } + } } diff --git a/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/model/SchedulerModel.java b/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/model/SchedulerModel.java index 1b6aba9a0b..f846973011 100644 --- a/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/model/SchedulerModel.java +++ b/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/model/SchedulerModel.java @@ -1,9 +1,13 @@ package gov.nasa.jpl.aerie.merlin.protocol.model; +import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; import gov.nasa.jpl.aerie.merlin.protocol.types.DurationType; +import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; import java.util.Map; public interface SchedulerModel { Map getDurationTypes(); + SerializedValue serializeDuration(final Duration duration); + Duration deserializeDuration(final SerializedValue serializedValue); } From 422ce2335c9936e22dfecc4cc6fe2a81683a181e Mon Sep 17 00:00:00 2001 From: maillard Date: Fri, 27 Oct 2023 14:13:01 -0700 Subject: [PATCH 2/5] Properly serialize and deserialize durations in scheduling --- .../jpl/aerie/scheduler/model/Problem.java | 2 + .../simulation/SimulationFacade.java | 9 +- .../scheduler/solver/PrioritySolver.java | 4 +- .../aerie/scheduler/FixedDurationTest.java | 2 +- .../aerie/scheduler/LongDurationPlanTest.java | 3 +- .../scheduler/ParametricDurationTest.java | 2 +- .../aerie/scheduler/PrioritySolverTest.java | 23 +++- .../aerie/scheduler/SimulationFacadeTest.java | 2 +- .../jpl/aerie/scheduler/TestApplyWhen.java | 115 ++++-------------- .../aerie/scheduler/TestCardinalityGoal.java | 12 +- .../aerie/scheduler/TestRecurrenceGoal.java | 14 +-- .../scheduler/TestRecurrenceGoalExtended.java | 42 ++----- .../TestUnsatisfiableCompositeGoals.java | 9 +- .../scheduler/UncontrollableDurationTest.java | 4 +- .../server/services/GraphQLMerlinService.java | 26 ++-- .../server/services/MerlinService.java | 10 +- .../services/SynchronousSchedulerAgent.java | 22 ++-- .../worker/services/MockMerlinService.java | 20 +-- 18 files changed, 125 insertions(+), 196 deletions(-) diff --git a/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/model/Problem.java b/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/model/Problem.java index 88fa116f46..01aa3d3f8f 100644 --- a/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/model/Problem.java +++ b/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/model/Problem.java @@ -100,6 +100,8 @@ public PlanningHorizon getPlanningHorizon(){ return planningHorizon; } + public SchedulerModel getSchedulerModel() { return schedulerModel; } + /** * adds a new global constraint to the mission model * diff --git a/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/simulation/SimulationFacade.java b/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/simulation/SimulationFacade.java index da1fb2fea0..8e93749cd2 100644 --- a/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/simulation/SimulationFacade.java +++ b/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/simulation/SimulationFacade.java @@ -6,6 +6,7 @@ import gov.nasa.jpl.aerie.merlin.driver.SerializedActivity; import gov.nasa.jpl.aerie.merlin.driver.SimulatedActivityId; import gov.nasa.jpl.aerie.merlin.driver.SimulationResults; +import gov.nasa.jpl.aerie.merlin.protocol.model.SchedulerModel; import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; import gov.nasa.jpl.aerie.merlin.protocol.types.DurationType; import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; @@ -32,6 +33,7 @@ public class SimulationFacade implements AutoCloseable{ private static final Logger logger = LoggerFactory.getLogger(SimulationFacade.class); private final MissionModel missionModel; + private final SchedulerModel schedulerModel; // planning horizon private final PlanningHorizon planningHorizon; @@ -100,7 +102,9 @@ public Optional getLatestDriverSimulationResults(){ return Optional.of(lastSimulationData.driverResults()); } - public SimulationFacade(final PlanningHorizon planningHorizon, final MissionModel missionModel) { + public SimulationFacade(final PlanningHorizon planningHorizon, + final MissionModel missionModel, + final SchedulerModel schedulerModel) { this.missionModel = missionModel; this.planningHorizon = planningHorizon; this.driver = new ResumableSimulationDriver<>(missionModel, planningHorizon.getAerieHorizonDuration()); @@ -110,6 +114,7 @@ public SimulationFacade(final PlanningHorizon planningHorizon, final MissionMode this.pastSimulationRestarts = 0; this.initialPlan = new ArrayList<>(); this.initialSimulationResults = Optional.empty(); + this.schedulerModel = schedulerModel; } @Override @@ -337,7 +342,7 @@ private ActivityDirective schedulingActToActivityDir(SchedulingActivityDirective if (activity.duration() != null) { final var durationType = activity.getType().getDurationType(); if (durationType instanceof DurationType.Controllable dt) { - arguments.put(dt.parameterName(), SerializedValue.of(activity.duration().in(Duration.MICROSECONDS))); + arguments.put(dt.parameterName(), this.schedulerModel.serializeDuration(activity.duration())); } else if ( durationType instanceof DurationType.Uncontrollable || durationType instanceof DurationType.Fixed diff --git a/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/solver/PrioritySolver.java b/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/solver/PrioritySolver.java index 1e6d898612..34c774a13d 100644 --- a/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/solver/PrioritySolver.java +++ b/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/solver/PrioritySolver.java @@ -1048,9 +1048,7 @@ public Duration valueAt(Duration start, final EquationSolvingAlgorithms.History< //handle variable duration parameter here final Duration setActivityDuration; if (instantiatedArguments.containsKey(durationParameterName)) { - final var argumentDuration = Duration.of( - instantiatedArguments.get(durationParameterName).asInt().get(), - Duration.MICROSECOND); + final var argumentDuration = problem.getSchedulerModel().deserializeDuration(instantiatedArguments.get(durationParameterName)); if (solved.duration().contains(argumentDuration)) { setActivityDuration = argumentDuration; } else { diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/FixedDurationTest.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/FixedDurationTest.java index 53cddc69d7..94e4bb38c7 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/FixedDurationTest.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/FixedDurationTest.java @@ -29,7 +29,7 @@ public class FixedDurationTest { void setUp(){ planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochDays(3)); MissionModel bananaMissionModel = SimulationUtility.getBananaMissionModel(); - problem = new Problem(bananaMissionModel, planningHorizon, new SimulationFacade(planningHorizon, bananaMissionModel), SimulationUtility.getBananaSchedulerModel()); + problem = new Problem(bananaMissionModel, planningHorizon, new SimulationFacade(planningHorizon, bananaMissionModel, SimulationUtility.getBananaSchedulerModel()), SimulationUtility.getBananaSchedulerModel()); } @Test diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/LongDurationPlanTest.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/LongDurationPlanTest.java index e27709886e..ce24bbdc21 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/LongDurationPlanTest.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/LongDurationPlanTest.java @@ -26,8 +26,7 @@ private static PrioritySolver makeProblemSolver(Problem problem) { //test mission with two primitive activity types private static Problem makeTestMissionAB() { - final var banananationMissionModel = SimulationUtility.getBananaMissionModel(); - return new Problem(banananationMissionModel, h, new SimulationFacade(h, banananationMissionModel), SimulationUtility.getBananaSchedulerModel()); + return SimulationUtility.buildProblemFromBanana(h); } private final static PlanningHorizon h = new PlanningHorizon(TimeUtility.fromDOY("2025-001T01:01:01.001"), TimeUtility.fromDOY("2030-005T01:01:01.001")); diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/ParametricDurationTest.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/ParametricDurationTest.java index 028e1a7229..129aaecd8b 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/ParametricDurationTest.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/ParametricDurationTest.java @@ -31,7 +31,7 @@ public class ParametricDurationTest { void setUp(){ planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochDays(3)); MissionModel bananaMissionModel = SimulationUtility.getBananaMissionModel(); - problem = new Problem(bananaMissionModel, planningHorizon, new SimulationFacade(planningHorizon, bananaMissionModel), SimulationUtility.getBananaSchedulerModel()); + problem = new Problem(bananaMissionModel, planningHorizon, new SimulationFacade(planningHorizon, bananaMissionModel, SimulationUtility.getBananaSchedulerModel()), SimulationUtility.getBananaSchedulerModel()); } @Test diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/PrioritySolverTest.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/PrioritySolverTest.java index 449d034252..8ca2ef3412 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/PrioritySolverTest.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/PrioritySolverTest.java @@ -31,12 +31,13 @@ public class PrioritySolverTest { private static PrioritySolver makeEmptyProblemSolver() { MissionModel bananaMissionModel = SimulationUtility.getBananaMissionModel(); + final var schedulerModel = SimulationUtility.getBananaSchedulerModel(); return new PrioritySolver( new Problem( bananaMissionModel, h, - new SimulationFacade(h, bananaMissionModel), - SimulationUtility.getBananaSchedulerModel())); + new SimulationFacade(h, bananaMissionModel, schedulerModel), + schedulerModel)); } private static PrioritySolver makeProblemSolver(Problem problem) { @@ -75,7 +76,8 @@ public void getNextSolution_givesNoSolutionOnSubsequentCall() { //test mission with two primitive activity types private static Problem makeTestMissionAB() { final var fooMissionModel = SimulationUtility.getFooMissionModel(); - return new Problem(fooMissionModel, h, new SimulationFacade(h, fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var fooSchedulerModel = SimulationUtility.getFooSchedulerModel(); + return new Problem(fooMissionModel, h, new SimulationFacade(h, fooMissionModel, fooSchedulerModel), fooSchedulerModel); } private final static PlanningHorizon h = new PlanningHorizon(TimeUtility.fromDOY("2025-001T01:01:01.001"), TimeUtility.fromDOY("2025-005T01:01:01.001")); @@ -241,7 +243,10 @@ public void getNextSolution_coexistenceGoalOnActivityWorks_withInitialSimResults { final var problem = makeTestMissionAB(); - final var adHocFacade = new SimulationFacade(problem.getPlanningHorizon(), problem.getMissionModel()); + final var adHocFacade = new SimulationFacade( + problem.getPlanningHorizon(), + problem.getMissionModel(), + problem.getSchedulerModel()); adHocFacade.insertActivitiesIntoSimulation(makePlanA012(problem).getActivities()); adHocFacade.computeSimulationResultsUntil(problem.getPlanningHorizon().getEndAerie()); final var simResults = adHocFacade.getLatestDriverSimulationResults().get(); @@ -276,9 +281,15 @@ public void testCardGoalWithApplyWhen(){ var planningHorizon = h; final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( + final var fooSchedulerModel = SimulationUtility.getFooSchedulerModel(); + Problem problem = new Problem( + fooMissionModel, planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + new SimulationFacade( + planningHorizon, + fooMissionModel, + fooSchedulerModel), + SimulationUtility.getFooSchedulerModel()); final var activityType = problem.getActivityType("ControllableDurationActivity"); //act at t=1hr and at t=2hrs diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/SimulationFacadeTest.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/SimulationFacadeTest.java index b18fff4b76..4cfb70bb47 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/SimulationFacadeTest.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/SimulationFacadeTest.java @@ -83,7 +83,7 @@ private DiscreteResource getPlantRes() { public void setUp() { missionModel = SimulationUtility.getBananaMissionModel(); final var schedulerModel = SimulationUtility.getBananaSchedulerModel(); - facade = new SimulationFacade(horizon, missionModel); + facade = new SimulationFacade(horizon, missionModel, schedulerModel); problem = new Problem(missionModel, horizon, facade, schedulerModel); } diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestApplyWhen.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestApplyWhen.java index 9759a0a46a..d1752321e4 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestApplyWhen.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestApplyWhen.java @@ -60,10 +60,7 @@ public class TestApplyWhen { @Test public void testRecurrenceCutoff1() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -96,10 +93,7 @@ public void testRecurrenceCutoff1() { @Test public void testRecurrenceCutoff2() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -132,10 +126,7 @@ public void testRecurrenceCutoff2() { @Test public void testRecurrenceShorterWindow() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -168,10 +159,7 @@ public void testRecurrenceShorterWindow() { @Test public void testRecurrenceLongerWindow() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -217,10 +205,7 @@ public void testRecurrenceBabyWindow() { RESULT: [+-------------------] */ var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -257,10 +242,7 @@ public void testRecurrenceWindows() { // RESULT: [++--------++--------] var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); final var goalWindow = new Windows(false).set(Arrays.asList( @@ -303,10 +285,7 @@ public void testRecurrenceWindowsCutoffMidInterval() { // RESULT: [++--------++--------] var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); final var goalWindow = new Windows(false).set(Arrays.asList( @@ -350,10 +329,7 @@ public void testRecurrenceWindowsGlobalCheck() { // RESULT: [++-----++-++----~~---] (if not global) var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); final var goalWindow = new Windows(false).set(List.of( @@ -398,10 +374,7 @@ public void testRecurrenceWindowsCutoffMidActivity() { // RESULT: [----------++--------] var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); final var goalWindow = new Windows(false).set(List.of( @@ -441,10 +414,7 @@ public void testRecurrenceWindowsCutoffMidActivity() { @Test public void testRecurrenceCutoffUncontrollable() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(21)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("BasicActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -482,9 +452,7 @@ public void testCardinality() { final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(25)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); TestUtility.createAutoMutexGlobalSchedulingCondition(activityType).forEach(problem::add); @@ -525,10 +493,7 @@ public void testCardinalityWindows() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); final var goalWindow = new Windows(false).set(List.of( @@ -575,10 +540,7 @@ public void testCardinalityWindowsCutoffMidActivity() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); final var goalWindow = new Windows(false).set(List.of( @@ -627,9 +589,7 @@ public void testCardinalityUncontrollable() { //ruled unpredictable for now final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(25)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("BasicActivity"); @@ -674,9 +634,7 @@ public void testCoexistenceWindowCutoff() { final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(25)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); //have some activity already present // create a PlanInMemory, add ActivityInstances @@ -729,9 +687,7 @@ public void testCoexistenceJustFits() { final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(25)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); //have some activity already present // create a PlanInMemory, add ActivityInstances @@ -791,9 +747,7 @@ public void testCoexistenceUncontrollableCutoff() { //ruled unpredictable for no final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(25)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); //have some activity already present // create a PlanInMemory, add ActivityInstances @@ -848,9 +802,7 @@ public void testCoexistenceWindows() { final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(25)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); //have some activity already present // create a PlanInMemory, add ActivityInstances @@ -915,9 +867,7 @@ public void testCoexistenceWindowsCutoffMidActivity() { final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(28)); //this boundary is inclusive. - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); //have some activity already present // create a PlanInMemory, add ActivityInstances @@ -994,9 +944,7 @@ public void testCoexistenceWindowsBisect() { //bad, should fail completely. wort final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(12)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); //have some activity already present // create a PlanInMemory, add ActivityInstances @@ -1062,9 +1010,7 @@ public void testCoexistenceWindowsBisect2() { //corrected. Bisection does work s final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(16)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); //have some activity already present // create a PlanInMemory, add ActivityInstances @@ -1128,9 +1074,7 @@ public void testCoexistenceUncontrollableJustFits() { final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(25)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); //have some activity already present // create a PlanInMemory, add ActivityInstances @@ -1237,10 +1181,7 @@ public void changingForAllTimeIn() { //basic setup PlanningHorizon hor = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, hor, new SimulationFacade( - hor, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(hor); final var activityTypeIndependent = problem.getActivityType("BasicFooActivity"); logger.debug("BasicFooActivity: " + activityTypeIndependent.toString()); @@ -1314,10 +1255,7 @@ public void changingForAllTimeInCutoff() { //basic setup PlanningHorizon hor = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(18)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, hor, new SimulationFacade( - hor, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(hor); final var activityTypeIndependent = problem.getActivityType("BasicFooActivity"); logger.debug("BasicFooActivity: " + activityTypeIndependent.toString()); @@ -1392,10 +1330,7 @@ public void changingForAllTimeInAlternativeCutoff() { //basic setup PlanningHorizon hor = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, hor, new SimulationFacade( - hor, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(hor); final var activityTypeIndependent = problem.getActivityType("BasicFooActivity"); logger.debug("BasicFooActivity: " + activityTypeIndependent.toString()); diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestCardinalityGoal.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestCardinalityGoal.java index cf841e9419..dfe915148d 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestCardinalityGoal.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestCardinalityGoal.java @@ -7,17 +7,15 @@ import gov.nasa.jpl.aerie.scheduler.constraints.activities.ActivityExpression; import gov.nasa.jpl.aerie.scheduler.goals.CardinalityGoal; import gov.nasa.jpl.aerie.scheduler.goals.ChildCustody; -import gov.nasa.jpl.aerie.scheduler.model.SchedulingActivityDirective; import gov.nasa.jpl.aerie.scheduler.model.PlanningHorizon; -import gov.nasa.jpl.aerie.scheduler.model.Problem; -import gov.nasa.jpl.aerie.scheduler.simulation.SimulationFacade; +import gov.nasa.jpl.aerie.scheduler.model.SchedulingActivityDirective; import gov.nasa.jpl.aerie.scheduler.solver.PrioritySolver; import org.junit.jupiter.api.Test; import java.util.List; +import static gov.nasa.jpl.aerie.scheduler.SimulationUtility.buildProblemFromFoo; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; public class TestCardinalityGoal { @@ -26,11 +24,9 @@ public class TestCardinalityGoal { public void testone() { Interval period = Interval.betweenClosedOpen(Duration.of(0, Duration.SECONDS), Duration.of(20, Duration.SECONDS)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(25)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); + CardinalityGoal goal = new CardinalityGoal.Builder() .duration(Interval.between(Duration.of(12, Duration.SECONDS), Duration.of(15, Duration.SECONDS))) diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestRecurrenceGoal.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestRecurrenceGoal.java index 4ee3516746..213661cd28 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestRecurrenceGoal.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestRecurrenceGoal.java @@ -14,6 +14,7 @@ import java.util.List; +import static gov.nasa.jpl.aerie.scheduler.SimulationUtility.buildProblemFromFoo; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -23,10 +24,7 @@ public class TestRecurrenceGoal { @Test public void testRecurrence() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -55,13 +53,7 @@ public void testRecurrence() { @Test public void testRecurrenceNegative() { final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, - planningHorizon, - new SimulationFacade(planningHorizon, - fooMissionModel), - SimulationUtility.getFooSchedulerModel()); - + final var problem = buildProblemFromFoo(planningHorizon); try { final var activityType = problem.getActivityType("ControllableDurationActivity"); final var goal = new RecurrenceGoal.Builder() diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestRecurrenceGoalExtended.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestRecurrenceGoalExtended.java index 7dfdcc37bb..2d02bcd585 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestRecurrenceGoalExtended.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestRecurrenceGoalExtended.java @@ -7,15 +7,13 @@ import gov.nasa.jpl.aerie.scheduler.constraints.activities.ActivityExpression; import gov.nasa.jpl.aerie.scheduler.goals.RecurrenceGoal; import gov.nasa.jpl.aerie.scheduler.model.PlanningHorizon; -import gov.nasa.jpl.aerie.scheduler.model.Problem; -import gov.nasa.jpl.aerie.scheduler.simulation.SimulationFacade; import gov.nasa.jpl.aerie.scheduler.solver.PrioritySolver; import org.junit.jupiter.api.Test; import java.util.List; +import static gov.nasa.jpl.aerie.scheduler.SimulationUtility.buildProblemFromFoo; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; public class TestRecurrenceGoalExtended { @@ -26,10 +24,7 @@ public class TestRecurrenceGoalExtended { @Test public void testRecurrence() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -61,10 +56,7 @@ public void testRecurrence() { @Test public void testRecurrenceSecondGoalOutOfWindowAndPlanHorizon() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -93,10 +85,7 @@ public void testRecurrenceSecondGoalOutOfWindowAndPlanHorizon() { @Test public void testRecurrenceRepeatIntervalLargerThanGoalWindow() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -125,10 +114,7 @@ public void testRecurrenceRepeatIntervalLargerThanGoalWindow() { @Test public void testGoalWindowLargerThanPlanHorizon() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(5),TestUtility.timeFromEpochSeconds(15)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); final var goalWindow = new Windows(false).set(List.of( Interval.between(Duration.of(1, Duration.SECONDS), Duration.of(5, Duration.SECONDS)), @@ -164,10 +150,7 @@ public void testGoalWindowLargerThanPlanHorizon() { @Test public void testGoalDurationLargerGoalWindow() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -197,10 +180,7 @@ public void testGoalDurationLargerGoalWindow() { @Test public void testGoalDurationLargerRepeatInterval() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -230,10 +210,7 @@ public void testGoalDurationLargerRepeatInterval() { @Test public void testAddActivityNonEmptyPlan() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0),TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); RecurrenceGoal goal = new RecurrenceGoal.Builder() .named("Test recurrence goal") @@ -251,8 +228,7 @@ public void testAddActivityNonEmptyPlan() { var plan = solver.getNextSolution().orElseThrow(); // Create a new problem with previous plan and add new goal interleaved two time units wrt original goal - Problem problem2 = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem2 = buildProblemFromFoo(planningHorizon); problem2.setInitialPlan(plan); RecurrenceGoal goal2 = new RecurrenceGoal.Builder() .named("Test recurrence goal 2") diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestUnsatisfiableCompositeGoals.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestUnsatisfiableCompositeGoals.java index 11f8d86bcf..d614be8081 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestUnsatisfiableCompositeGoals.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestUnsatisfiableCompositeGoals.java @@ -24,6 +24,7 @@ import java.util.List; +import static gov.nasa.jpl.aerie.scheduler.SimulationUtility.buildProblemFromFoo; import static org.junit.jupiter.api.Assertions.assertEquals; public class TestUnsatisfiableCompositeGoals { @@ -41,8 +42,7 @@ public class TestUnsatisfiableCompositeGoals { //test mission with two primitive activity types private static Problem makeTestMissionAB() { - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - return new Problem(fooMissionModel, h, new SimulationFacade(h, fooMissionModel), SimulationUtility.getFooSchedulerModel()); + return SimulationUtility.buildProblemFromFoo(h); } private static PlanInMemory makePlanA12(Problem problem) { @@ -218,10 +218,7 @@ public void testOrWithBacktrack(){ public void testCardinalityBacktrack() { var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(20)); - final var fooMissionModel = SimulationUtility.getFooMissionModel(); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( - planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + final var problem = buildProblemFromFoo(planningHorizon); final var activityType = problem.getActivityType("ControllableDurationActivity"); final var goalWindow = new Windows(false).set(List.of( diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/UncontrollableDurationTest.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/UncontrollableDurationTest.java index d79ab600a9..9d6d4a0b74 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/UncontrollableDurationTest.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/UncontrollableDurationTest.java @@ -25,6 +25,7 @@ import java.util.List; +import static gov.nasa.jpl.aerie.scheduler.SimulationUtility.buildProblemFromFoo; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -37,8 +38,7 @@ public class UncontrollableDurationTest { @BeforeEach void setUp(){ planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(3000)); - MissionModel aerieLanderMissionModel = SimulationUtility.getFooMissionModel(); - problem = new Problem(aerieLanderMissionModel, planningHorizon, new SimulationFacade(planningHorizon, aerieLanderMissionModel), SimulationUtility.getFooSchedulerModel()); + problem = buildProblemFromFoo(planningHorizon); plan = makeEmptyPlan(); } diff --git a/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/GraphQLMerlinService.java b/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/GraphQLMerlinService.java index 58efd0e1ed..c7f7bcb380 100644 --- a/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/GraphQLMerlinService.java +++ b/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/GraphQLMerlinService.java @@ -12,6 +12,7 @@ import gov.nasa.jpl.aerie.merlin.driver.UnfinishedActivity; import gov.nasa.jpl.aerie.merlin.driver.engine.ProfileSegment; import gov.nasa.jpl.aerie.merlin.driver.timeline.EventGraph; +import gov.nasa.jpl.aerie.merlin.protocol.model.SchedulerModel; import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; import gov.nasa.jpl.aerie.merlin.protocol.types.DurationType; import gov.nasa.jpl.aerie.merlin.protocol.types.InstantiationException; @@ -26,6 +27,7 @@ import gov.nasa.jpl.aerie.scheduler.server.exceptions.NoSuchMissionModelException; import gov.nasa.jpl.aerie.scheduler.server.exceptions.NoSuchPlanException; import gov.nasa.jpl.aerie.scheduler.server.graphql.GraphQLParsers; +import gov.nasa.jpl.aerie.scheduler.server.graphql.ProfileParsers; import gov.nasa.jpl.aerie.scheduler.server.http.EventGraphFlattener; import gov.nasa.jpl.aerie.scheduler.server.http.InvalidEntityException; import gov.nasa.jpl.aerie.scheduler.server.http.InvalidJsonException; @@ -360,7 +362,8 @@ public String getNextPlanName() { public Pair> createNewPlanWithActivityDirectives( final PlanMetadata planMetadata, final Plan plan, - final Map activityToGoalId + final Map activityToGoalId, + final SchedulerModel schedulerModel ) throws IOException, NoSuchPlanException, MerlinServiceException { @@ -368,7 +371,7 @@ public Pair> creat final var planId = createEmptyPlan( planName, planMetadata.modelId(), planMetadata.horizon().getStartInstant(), planMetadata.horizon().getEndAerie()); - final Map activityToId = createAllPlanActivityDirectives(planId, plan, activityToGoalId); + final Map activityToId = createAllPlanActivityDirectives(planId, plan, activityToGoalId, schedulerModel); return Pair.of(planId, activityToId); } @@ -413,8 +416,9 @@ public Map updatePlanActivityD final Map idsFromInitialPlan, final MerlinPlan initialPlan, final Plan plan, - final Map activityToGoalId - ) + final Map activityToGoalId, + final SchedulerModel schedulerModel + ) throws IOException, NoSuchPlanException, MerlinServiceException { final var ids = new HashMap(); @@ -427,7 +431,7 @@ public Map updatePlanActivityD //add duration to parameters if controllable if (activity.getType().getDurationType() instanceof DurationType.Controllable durationType){ if (!activity.arguments().containsKey(durationType.parameterName())){ - activity.addArgument(durationType.parameterName(), SerializedValue.of(activity.duration().in(Duration.MICROSECONDS))); + activity.addArgument(durationType.parameterName(), schedulerModel.serializeDuration(activity.duration())); } } final var actFromInitialPlan = initialPlan.getActivityById(idActFromInitialPlan); @@ -459,7 +463,7 @@ public Map updatePlanActivityD } //Create - ids.putAll(createActivityDirectives(planId, toAdd, activityToGoalId)); + ids.putAll(createActivityDirectives(planId, toAdd, activityToGoalId, schedulerModel)); return ids; } @@ -522,17 +526,19 @@ public void clearPlanActivityDirectives(final PlanId planId) throws IOException, public Map createAllPlanActivityDirectives( final PlanId planId, final Plan plan, - final Map activityToGoalId + final Map activityToGoalId, + final SchedulerModel schedulerModel ) throws IOException, NoSuchPlanException, MerlinServiceException { - return createActivityDirectives(planId, plan.getActivitiesByTime(), activityToGoalId); + return createActivityDirectives(planId, plan.getActivitiesByTime(), activityToGoalId, schedulerModel); } public Map createActivityDirectives( final PlanId planId, final List orderedActivities, - final Map activityToGoalId + final Map activityToGoalId, + final SchedulerModel schedulerModel ) throws IOException, NoSuchPlanException, MerlinServiceException { @@ -564,7 +570,7 @@ mutation createAllPlanActivityDirectives($activities: [activity_directive_insert final var insertionObjectArguments = Json.createObjectBuilder(); if(act.getType().getDurationType() instanceof DurationType.Controllable durationType){ if(!act.arguments().containsKey(durationType.parameterName())){ - insertionObjectArguments.add(durationType.parameterName(), act.duration().in(Duration.MICROSECOND)); + insertionObjectArguments.add(durationType.parameterName(), serializedValueP.unparse(schedulerModel.serializeDuration(act.duration()))); } } diff --git a/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/MerlinService.java b/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/MerlinService.java index c6aea10d5f..2c54013e11 100644 --- a/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/MerlinService.java +++ b/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/MerlinService.java @@ -2,6 +2,7 @@ import gov.nasa.jpl.aerie.merlin.driver.ActivityDirectiveId; import gov.nasa.jpl.aerie.merlin.driver.SimulationResults; +import gov.nasa.jpl.aerie.merlin.protocol.model.SchedulerModel; import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; import gov.nasa.jpl.aerie.merlin.protocol.types.InstantiationException; import gov.nasa.jpl.aerie.scheduler.model.Plan; @@ -124,7 +125,8 @@ interface WriterRole { Pair> createNewPlanWithActivityDirectives( final PlanMetadata planMetadata, final Plan plan, - final Map activityToGoalId + final Map activityToGoalId, + final SchedulerModel schedulerModel ) throws IOException, NoSuchPlanException, MerlinServiceException; @@ -158,7 +160,8 @@ Map updatePlanActivityDirectiv Map idsFromInitialPlan, MerlinPlan initialPlan, Plan plan, - Map activityToGoalId + Map activityToGoalId, + SchedulerModel schedulerModel ) throws IOException, NoSuchPlanException, MerlinServiceException, NoSuchActivityInstanceException; @@ -188,7 +191,8 @@ void clearPlanActivityDirectives(final PlanId planId) Map createAllPlanActivityDirectives( final PlanId planId, final Plan plan, - final Map activityToGoalId + final Map activityToGoalId, + final SchedulerModel schedulerModel ) throws IOException, NoSuchPlanException, MerlinServiceException; diff --git a/scheduler-worker/src/main/java/gov/nasa/jpl/aerie/scheduler/worker/services/SynchronousSchedulerAgent.java b/scheduler-worker/src/main/java/gov/nasa/jpl/aerie/scheduler/worker/services/SynchronousSchedulerAgent.java index b2ad52cd70..806b8bcd73 100644 --- a/scheduler-worker/src/main/java/gov/nasa/jpl/aerie/scheduler/worker/services/SynchronousSchedulerAgent.java +++ b/scheduler-worker/src/main/java/gov/nasa/jpl/aerie/scheduler/worker/services/SynchronousSchedulerAgent.java @@ -122,7 +122,10 @@ public void schedule(final ScheduleRequest request, final ResultsProtocol.Writer specification.horizonStartTimestamp().toInstant(), specification.horizonEndTimestamp().toInstant() ); - try(final var simulationFacade = new SimulationFacade(planningHorizon, schedulerMissionModel.missionModel())) { + try(final var simulationFacade = new SimulationFacade( + planningHorizon, + schedulerMissionModel.missionModel(), + schedulerMissionModel.schedulerModel())) { final var problem = new Problem( schedulerMissionModel.missionModel(), planningHorizon, @@ -229,7 +232,8 @@ public void schedule(final ScheduleRequest request, final ResultsProtocol.Writer loadedPlanComponents.idMap(), loadedPlanComponents.merlinPlan(), solutionPlan, - activityToGoalId + activityToGoalId, + schedulerMissionModel.schedulerModel() ); final var planMetadataAfterChanges = merlinService.getPlanMetadata(specification.planId()); final var datasetId = storeSimulationResults(planningHorizon, simulationFacade, planMetadataAfterChanges, instancesToIds); @@ -429,11 +433,7 @@ private PlanComponents loadInitialPlan( if (schedulerActType.getDurationType() instanceof DurationType.Controllable s) { final var serializedDuration = activity.serializedActivity().getArguments().get(s.parameterName()); if (serializedDuration != null) { - actDuration = Duration.of( - serializedDuration - .asInt() - .orElseThrow(() -> new Exception("Controllable Duration parameter was not an Int")), - Duration.MICROSECONDS); + actDuration = problem.getSchedulerModel().deserializeDuration(serializedDuration); } } else if (schedulerActType.getDurationType() instanceof DurationType.Fixed fixedDurationType) { actDuration = fixedDurationType.duration(); @@ -577,12 +577,13 @@ private Map storeFinalPlan( final Map idsFromInitialPlan, final MerlinPlan initialPlan, final Plan newPlan, - final Map goalToActivity + final Map goalToActivity, + final SchedulerModel schedulerModel ) { try { switch (this.outputMode) { case CreateNewOutputPlan -> { - return merlinService.createNewPlanWithActivityDirectives(planMetadata, newPlan, goalToActivity).getValue(); + return merlinService.createNewPlanWithActivityDirectives(planMetadata, newPlan, goalToActivity, schedulerModel).getValue(); } case UpdateInputPlanWithNewActivities -> { return merlinService.updatePlanActivityDirectives( @@ -590,7 +591,8 @@ private Map storeFinalPlan( idsFromInitialPlan, initialPlan, newPlan, - goalToActivity + goalToActivity, + schedulerModel ); } default -> throw new IllegalArgumentException("unsupported scheduler output mode " + this.outputMode); diff --git a/scheduler-worker/src/test/java/gov/nasa/jpl/aerie/scheduler/worker/services/MockMerlinService.java b/scheduler-worker/src/test/java/gov/nasa/jpl/aerie/scheduler/worker/services/MockMerlinService.java index bd5b005f66..b3fd375ae5 100644 --- a/scheduler-worker/src/test/java/gov/nasa/jpl/aerie/scheduler/worker/services/MockMerlinService.java +++ b/scheduler-worker/src/test/java/gov/nasa/jpl/aerie/scheduler/worker/services/MockMerlinService.java @@ -3,6 +3,7 @@ import gov.nasa.jpl.aerie.merlin.driver.ActivityDirective; import gov.nasa.jpl.aerie.merlin.driver.ActivityDirectiveId; import gov.nasa.jpl.aerie.merlin.driver.SimulationResults; +import gov.nasa.jpl.aerie.merlin.protocol.model.SchedulerModel; import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; import gov.nasa.jpl.aerie.merlin.protocol.types.DurationType; import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; @@ -106,7 +107,8 @@ public MerlinPlan getPlanActivityDirectives(final PlanMetadata planMetadata, fin public Pair> createNewPlanWithActivityDirectives( final PlanMetadata planMetadata, final Plan plan, - final Map activityToGoal + final Map activityToGoal, + final SchedulerModel schedulerModel ) { return null; @@ -124,10 +126,11 @@ public Map updatePlanActivityD final Map idsFromInitialPlan, final MerlinPlan initialPlan, final Plan plan, - final Map activityToGoal + final Map activityToGoal, + final SchedulerModel schedulerModel ) { - this.updatedPlan = extractActivityDirectives(plan); + this.updatedPlan = extractActivityDirectives(plan, schedulerModel); this.plan = plan; final var res = new HashMap(); for (final var activity : plan.getActivities()) { @@ -168,8 +171,9 @@ public void clearPlanActivityDirectives(final PlanId planId) public Map createAllPlanActivityDirectives( final PlanId planId, final Plan plan, - final Map activityToGoalId - ) + final Map activityToGoalId, + final SchedulerModel schedulerModel + ) { return null; } @@ -198,7 +202,7 @@ public MerlinService.MissionModelTypes getMissionModelTypes(final MissionModelId } - private static Collection extractActivityDirectives(final Plan plan) { + private static Collection extractActivityDirectives(final Plan plan, final SchedulerModel schedulerModel) { final var activityDirectives = new ArrayList(); for (final var activity : plan.getActivities()) { final var type = activity.getType(); @@ -206,7 +210,9 @@ private static Collection extractActivityDirectives(final Pla if(type.getDurationType() instanceof DurationType.Controllable durationType){ //detect duration parameter and add it to parameters if(!arguments.containsKey(durationType.parameterName())){ - arguments.put(durationType.parameterName(), SerializedValue.of(activity.duration().in(Duration.MICROSECONDS))); + arguments.put( + durationType.parameterName(), + schedulerModel.serializeDuration(activity.duration())); } } activityDirectives.add(new ActivityDirective( From b4aca18d10f33e8c302b1d250ad306db310fd212 Mon Sep 17 00:00:00 2001 From: maillard Date: Wed, 15 Nov 2023 13:25:02 -0800 Subject: [PATCH 3/5] Add custom duration value mapper to foo --- .../mappers/FooValueMappers.java | 5 +++ .../mappers/SmartestDurationValueMapper.java | 35 +++++++++++++++++++ .../aerie/foomissionmodel/package-info.java | 2 +- .../aerie/scheduler/SimulationUtility.java | 29 +++++++++++++++ .../jpl/aerie/scheduler/TestApplyWhen.java | 15 +++++--- .../simulation/ResumableSimulationTest.java | 5 ++- 6 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/mappers/SmartestDurationValueMapper.java diff --git a/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/mappers/FooValueMappers.java b/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/mappers/FooValueMappers.java index 6015028b93..de54a83591 100644 --- a/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/mappers/FooValueMappers.java +++ b/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/mappers/FooValueMappers.java @@ -2,10 +2,15 @@ import gov.nasa.jpl.aerie.contrib.serialization.mappers.Vector3DValueMapper; import gov.nasa.jpl.aerie.merlin.framework.ValueMapper; +import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; public class FooValueMappers { public static ValueMapper vector3d(final ValueMapper elementMapper) { return new Vector3DValueMapper(elementMapper); } + + public static ValueMapper duration(){ + return new SmartestDurationValueMapper(); + } } diff --git a/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/mappers/SmartestDurationValueMapper.java b/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/mappers/SmartestDurationValueMapper.java new file mode 100644 index 0000000000..29dc816294 --- /dev/null +++ b/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/mappers/SmartestDurationValueMapper.java @@ -0,0 +1,35 @@ +package gov.nasa.jpl.aerie.foomissionmodel.mappers; + +import gov.nasa.jpl.aerie.merlin.framework.Result; +import gov.nasa.jpl.aerie.merlin.framework.ValueMapper; +import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; +import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; +import gov.nasa.jpl.aerie.merlin.protocol.types.ValueSchema; + +import java.util.Map; + +public class SmartestDurationValueMapper implements ValueMapper { + + final static String FIELD_NAME = "amountInMicroseconds"; + + @Override + public ValueSchema getValueSchema() { + return ValueSchema.ofStruct( + Map.of(FIELD_NAME, ValueSchema.INT) + ); + } + + @Override + public Result deserializeValue(final SerializedValue serializedValue) { + final var asMap = serializedValue.asMap(); + if(asMap.isEmpty() || !asMap.get().containsKey(FIELD_NAME)){ + return Result.failure("failed to deserialize duration as map or a required field is not present"); + } + return Result.success(Duration.of(asMap.get().get(FIELD_NAME).asInt().get(), Duration.MICROSECONDS)); + } + + @Override + public SerializedValue serializeValue(final Duration value) { + return SerializedValue.of(Map.of(FIELD_NAME, SerializedValue.of(value.in(Duration.MICROSECONDS)))); + } +} diff --git a/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/package-info.java b/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/package-info.java index 1a0637363a..5bea32e5e8 100644 --- a/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/package-info.java +++ b/examples/foo-missionmodel/src/main/java/gov/nasa/jpl/aerie/foomissionmodel/package-info.java @@ -2,8 +2,8 @@ @WithConfiguration(Configuration.class) -@WithMappers(BasicValueMappers.class) @WithMappers(FooValueMappers.class) +@WithMappers(BasicValueMappers.class) @WithActivityType(BasicActivity.class) @WithActivityType(FooActivity.class) diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/SimulationUtility.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/SimulationUtility.java index 2d84ce94a1..c39584e4b1 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/SimulationUtility.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/SimulationUtility.java @@ -6,6 +6,9 @@ import gov.nasa.jpl.aerie.merlin.driver.MissionModel; import gov.nasa.jpl.aerie.merlin.driver.MissionModelBuilder; import gov.nasa.jpl.aerie.merlin.protocol.model.SchedulerModel; +import gov.nasa.jpl.aerie.scheduler.model.PlanningHorizon; +import gov.nasa.jpl.aerie.scheduler.model.Problem; +import gov.nasa.jpl.aerie.scheduler.simulation.SimulationFacade; import java.nio.file.Path; import java.time.Instant; @@ -29,6 +32,32 @@ private static MissionModel makeMissionModel(final MissionModelBuilder builde return builder.build(model, registry); } + public static Problem buildProblemFromFoo(final PlanningHorizon planningHorizon){ + final var fooMissionModel = SimulationUtility.getFooMissionModel(); + final var fooSchedulerModel = SimulationUtility.getFooSchedulerModel(); + return new Problem( + fooMissionModel, + planningHorizon, + new SimulationFacade( + planningHorizon, + fooMissionModel, + fooSchedulerModel), + fooSchedulerModel); + } + + public static Problem buildProblemFromBanana(final PlanningHorizon planningHorizon){ + final var fooMissionModel = SimulationUtility.getBananaMissionModel(); + final var fooSchedulerModel = SimulationUtility.getBananaSchedulerModel(); + return new Problem( + fooMissionModel, + planningHorizon, + new SimulationFacade( + planningHorizon, + fooMissionModel, + fooSchedulerModel), + fooSchedulerModel); + } + public static SchedulerModel getFooSchedulerModel(){ return new gov.nasa.jpl.aerie.foomissionmodel.generated.GeneratedSchedulerModel(); } diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestApplyWhen.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestApplyWhen.java index d1752321e4..32a427a283 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestApplyWhen.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/TestApplyWhen.java @@ -48,6 +48,7 @@ import java.util.Map; import java.util.Set; +import static gov.nasa.jpl.aerie.scheduler.SimulationUtility.buildProblemFromFoo; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -1121,12 +1122,18 @@ public void testCoexistenceExternalResource() { Interval period = Interval.betweenClosedOpen(Duration.of(0, Duration.SECONDS), Duration.of(25, Duration.SECONDS)); final var fooMissionModel = SimulationUtility.getFooMissionModel(); + final var fooSchedulerMissionModel = SimulationUtility.getFooSchedulerModel(); final var planningHorizon = new PlanningHorizon(TestUtility.timeFromEpochSeconds(0), TestUtility.timeFromEpochSeconds(25)); - Problem problem = new Problem(fooMissionModel, planningHorizon, new SimulationFacade( + Problem problem = new Problem( + fooMissionModel, planningHorizon, - fooMissionModel), SimulationUtility.getFooSchedulerModel()); + new SimulationFacade( + planningHorizon, + fooMissionModel, + fooSchedulerMissionModel), + fooSchedulerMissionModel); - final var r3Value = 6; + final var r3Value = Map.of("amountInMicroseconds", SerializedValue.of(6)); final var r1 = new LinearProfile(new Segment<>(Interval.between(Duration.ZERO, Duration.SECONDS.times(5)), new LinearEquation(Duration.ZERO, 5, 1))); final var r2 = new DiscreteProfile(new Segment<>(Interval.FOREVER, SerializedValue.of(5))); final var r3 = new DiscreteProfile(new Segment<>(Interval.FOREVER, SerializedValue.of(r3Value))); @@ -1170,7 +1177,7 @@ public void testCoexistenceExternalResource() { final var startOfActivity = cond.evaluate(emptySimulationResults, Interval.FOREVER, new EvaluationEnvironment(externalRealProfiles, externalDiscreteProfiles)).iterateEqualTo(true).iterator().next().start; assertEquals(1, plan.get().getActivitiesByTime().size()); final var act = plan.get().getActivitiesByTime().get(0); - assertEquals(act.duration(), Duration.of(r3Value, Duration.MICROSECONDS)); + assertEquals(act.duration(), Duration.of(r3Value.get("amountInMicroseconds").asInt().get(), Duration.MICROSECONDS)); assertEquals(startOfActivity, Duration.of(1, Duration.SECONDS)); assertEquals(act.startOffset(), startOfActivity); assertEquals(2, problem.getSimulationFacade().countSimulationRestarts()); diff --git a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/simulation/ResumableSimulationTest.java b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/simulation/ResumableSimulationTest.java index 38f1413481..de9dbf8ee6 100644 --- a/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/simulation/ResumableSimulationTest.java +++ b/scheduler-driver/src/test/java/gov/nasa/jpl/aerie/scheduler/simulation/ResumableSimulationTest.java @@ -4,7 +4,6 @@ import gov.nasa.jpl.aerie.merlin.driver.SerializedActivity; import gov.nasa.jpl.aerie.merlin.driver.engine.SimulationEngine; import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; -import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; import gov.nasa.jpl.aerie.scheduler.SimulationUtility; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -14,7 +13,6 @@ import java.util.Map; import java.util.concurrent.ThreadPoolExecutor; -import static gov.nasa.jpl.aerie.merlin.protocol.types.Duration.MICROSECOND; import static gov.nasa.jpl.aerie.merlin.protocol.types.Duration.SECONDS; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -80,9 +78,10 @@ public void durationTest(){ @Test public void testStopsAtEndOfPlanningHorizon(){ + final var fooSchedulerModel = SimulationUtility.getFooSchedulerModel(); final var activity = new TestSimulatedActivity( Duration.of(0, SECONDS), - new SerializedActivity("ControllableDurationActivity", Map.of("duration", SerializedValue.of(tenHours.in(MICROSECOND)))), + new SerializedActivity("ControllableDurationActivity", Map.of("duration", fooSchedulerModel.serializeDuration(tenHours))), new ActivityDirectiveId(1)); final var fooMissionModel = SimulationUtility.getFooMissionModel(); resumableSimulationDriver = new ResumableSimulationDriver<>(fooMissionModel, fiveHours); From e6b57e756e0ccc8604b13992b80d2279c2977949 Mon Sep 17 00:00:00 2001 From: maillard Date: Wed, 15 Nov 2023 18:58:06 -0800 Subject: [PATCH 4/5] Change e2eTest text block assert to line by line assert because of variability in order of resources --- .../src/test/java/gov/nasa/jpl/aerie/e2e/SchedulingTests.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/SchedulingTests.java b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/SchedulingTests.java index d7590d1963..d2ae9ffd9a 100644 --- a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/SchedulingTests.java +++ b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/SchedulingTests.java @@ -683,7 +683,9 @@ void schedulingDSLGeneratesExternalTypes() throws IOException { "/producer": string, }; """; - assertTrue(findFile.get(0).content().contains(resources)); + for(final var resourcesLine: resources.split("\n")){ + assertTrue(findFile.get(0).content().contains(resourcesLine)); + } } /** From 63cf8d48af8019d4a32c659e1a27f698f591cf5f Mon Sep 17 00:00:00 2001 From: Theresa Kamerman Date: Thu, 16 Nov 2023 14:03:17 -0800 Subject: [PATCH 5/5] Update Scheduling e2eTest to isolate compared region to exported Resource type --- .../nasa/jpl/aerie/e2e/SchedulingTests.java | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/SchedulingTests.java b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/SchedulingTests.java index d2ae9ffd9a..7f5b60ded4 100644 --- a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/SchedulingTests.java +++ b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/SchedulingTests.java @@ -20,6 +20,7 @@ import javax.json.JsonObject; import javax.json.JsonValue; import java.io.IOException; +import java.util.Arrays; import java.util.Comparator; import java.util.List; @@ -671,21 +672,28 @@ void schedulingDSLGeneratesExternalTypes() throws IOException { .toList(); assertEquals(1, findFile.size()); - final var resources = """ - export type Resource = { - "/peel": number, - "/my_boolean": boolean, - "/fruit": {initial: number, rate: number, }, - "/data/line_count": number, - "/flag/conflicted": boolean, - "/plant": number, - "/flag": ( | "A" | "B"), - "/producer": string, - }; - """; - for(final var resourcesLine: resources.split("\n")){ - assertTrue(findFile.get(0).content().contains(resourcesLine)); - } + // Create a list of the exported resource types, one entry per new line + final List resourceTypes = Arrays.stream(findFile.get(0) + .content() + .split("export type Resource = \\{\\n")[1] + .split("\\n};")[0] // isolate to export type Resource block + .split("\\n")) + .map(String::strip) // remove whitespace + .toList(); + + final var expectedResources = List.of( + "\"/data/line_count\": number,", + "\"/flag\": ( | \"A\" | \"B\"),", + "\"/flag/conflicted\": boolean,", + "\"/fruit\": {initial: number, rate: number, },", + "\"/my_boolean\": boolean,", + "\"/peel\": number,", + "\"/plant\": number,", + "\"/producer\": string," + ); + + assertEquals(expectedResources.size(), resourceTypes.size()); + assertTrue(resourceTypes.containsAll(expectedResources)); } /**