From 59c5303a43f87e775c823b02f5bccaeae041df30 Mon Sep 17 00:00:00 2001 From: Cody Hansen Date: Wed, 31 Jan 2024 06:40:45 -1000 Subject: [PATCH 1/3] Fixed an issue where constraint runs would fail against activities with unitized variants --- .../nasa/jpl/aerie/e2e/ConstraintsTests.java | 48 +++++++++++++++++++ .../activities/PeelBananaActivity.java | 2 + .../driver/json/ValueSchemaJsonParser.java | 1 + 3 files changed, 51 insertions(+) diff --git a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/ConstraintsTests.java b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/ConstraintsTests.java index fd91e68acc..bc443b9630 100644 --- a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/ConstraintsTests.java +++ b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/ConstraintsTests.java @@ -132,6 +132,54 @@ void constraintsSucceedOneViolation() throws IOException { assertTrue(constraintResult.gaps().isEmpty()); } + @Test + void constraintsSucceedAgainstVariantWithUnits() throws IOException { + hasura.deleteActivity(planId, activityId); + hasura.deleteConstraint(constraintId); + var fruitConstraintName = "fruit_equals_3"; + var fruitConstraintId = hasura.insertPlanConstraint( + fruitConstraintName, + planId, + "export default (): Constraint => Real.Resource(\"/fruit\").equal(3)", + ""); + hasura.insertActivity( + planId, + "PeelBanana", + "1h", + Json.createObjectBuilder().add("peelDirection", "fromStem").build()); + + hasura.awaitSimulation(planId); + final var constraintsResponses = hasura.checkConstraints(planId); + assertEquals(1, constraintsResponses.size()); + + // Check the Response + final var constraintResponse = constraintsResponses.get(0); + assertTrue(constraintResponse.success()); + assertEquals(fruitConstraintId, constraintResponse.constraintId()); + assertEquals(fruitConstraintName, constraintResponse.constraintName()); + assertEquals("plan", constraintResponse.type()); + // Check the Result + assertTrue(constraintResponse.result().isPresent()); + final var constraintResult = constraintResponse.result().get(); + // Resources + final var resources = constraintResult.resourceIds(); + assertEquals(1, resources.size()); + assertTrue(resources.contains("/fruit")); + + // Violation + assertEquals(1, constraintResult.violations().size()); + final var violation = constraintResult.violations().get(0); + assertEquals(1, violation.windows().size()); + + final long activityOffset = 60 * 60 * 1000000L; // 1h in micros + final long planDuration = 1212 * 60 * 60 * 1000000L; // 1212h in micros + + assertEquals(activityOffset, violation.windows().get(0).start()); + assertEquals(planDuration, violation.windows().get(0).end()); + // Gaps + assertTrue(constraintResult.gaps().isEmpty()); + } + @Test void constraintsSucceedNoViolations() throws IOException { // Delete activity to avoid violation diff --git a/examples/banananation/src/main/java/gov/nasa/jpl/aerie/banananation/activities/PeelBananaActivity.java b/examples/banananation/src/main/java/gov/nasa/jpl/aerie/banananation/activities/PeelBananaActivity.java index be6006d8c2..4436e29bb0 100644 --- a/examples/banananation/src/main/java/gov/nasa/jpl/aerie/banananation/activities/PeelBananaActivity.java +++ b/examples/banananation/src/main/java/gov/nasa/jpl/aerie/banananation/activities/PeelBananaActivity.java @@ -1,6 +1,7 @@ package gov.nasa.jpl.aerie.banananation.activities; import gov.nasa.jpl.aerie.banananation.Mission; +import gov.nasa.jpl.aerie.contrib.metadata.Unit; import gov.nasa.jpl.aerie.merlin.framework.annotations.ActivityType; import gov.nasa.jpl.aerie.merlin.framework.annotations.ActivityType.EffectModel; import gov.nasa.jpl.aerie.merlin.framework.annotations.Export.Parameter; @@ -25,6 +26,7 @@ public enum PeelDirectionEnum { } @Parameter + @Unit("direction") public PeelDirectionEnum peelDirection = PeelDirectionEnum.fromStem; @EffectModel diff --git a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/json/ValueSchemaJsonParser.java b/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/json/ValueSchemaJsonParser.java index 810e20ea63..b369d676d7 100644 --- a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/json/ValueSchemaJsonParser.java +++ b/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/json/ValueSchemaJsonParser.java @@ -94,6 +94,7 @@ private JsonParseResult parseVariant(final JsonObject obj) { productP .field("type", literalP("variant")) .field("variants", listP(variantP)) + .rest() .map( untuple((type, variants) -> ValueSchema.ofVariant(variants)), $ -> tuple(Unit.UNIT, $.asVariant().get())); From f49294b66f8d7f3fed25f48eeb94c77eeb40a91c Mon Sep 17 00:00:00 2001 From: Cody Hansen Date: Wed, 31 Jan 2024 07:03:43 -1000 Subject: [PATCH 2/3] Fixed the new constraint test --- .../test/java/gov/nasa/jpl/aerie/e2e/ConstraintsTests.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/ConstraintsTests.java b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/ConstraintsTests.java index bc443b9630..505843644b 100644 --- a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/ConstraintsTests.java +++ b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/ConstraintsTests.java @@ -172,10 +172,9 @@ void constraintsSucceedAgainstVariantWithUnits() throws IOException { assertEquals(1, violation.windows().size()); final long activityOffset = 60 * 60 * 1000000L; // 1h in micros - final long planDuration = 1212 * 60 * 60 * 1000000L; // 1212h in micros - assertEquals(activityOffset, violation.windows().get(0).start()); - assertEquals(planDuration, violation.windows().get(0).end()); + assertEquals(0, violation.windows().get(0).start()); + assertEquals(activityOffset, violation.windows().get(0).end()); // Gaps assertTrue(constraintResult.gaps().isEmpty()); } From 795b547c97172666daf566103a4bed30cd6754a9 Mon Sep 17 00:00:00 2001 From: Cody Hansen Date: Wed, 31 Jan 2024 07:30:55 -1000 Subject: [PATCH 3/3] Added the new metadata to fix our activity upload test --- .../java/gov/nasa/jpl/aerie/e2e/MissionModelTests.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/MissionModelTests.java b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/MissionModelTests.java index 99fb616742..7947734f12 100644 --- a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/MissionModelTests.java +++ b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/MissionModelTests.java @@ -311,9 +311,11 @@ private ArrayList expectedActivityTypesBanananation() { activityTypes.add(new ActivityType( "PeelBanana", Map.of("peelDirection", - new Parameter(0, new ValueSchemaVariant(List.of( - new Variant("fromStem", "fromStem"), - new Variant("fromTip", "fromTip"))))))); + new Parameter(0, + new ValueSchemaMeta(Map.of("unit", Json.createObjectBuilder(Map.of("value", "direction")).build()), + new ValueSchemaVariant(List.of( + new Variant("fromStem", "fromStem"), + new Variant("fromTip", "fromTip")))))))); activityTypes.add(new ActivityType("PickBanana", Map.of("quantity", new Parameter(0, VALUE_SCHEMA_INT)))); activityTypes.add(new ActivityType("RipenBanana", Map.of())); activityTypes.add(new ActivityType("ThrowBanana", Map.of("speed", new Parameter(0, VALUE_SCHEMA_REAL))));