From 052e69dd55f093d18fba3d5aaa8a7791a07ee042 Mon Sep 17 00:00:00 2001 From: JoelCourtney Date: Thu, 14 Sep 2023 12:44:31 -0700 Subject: [PATCH] Add tests --- .../jpl/aerie/constraints/time/Spans.java | 3 +- .../jpl/aerie/constraints/tree/ASTTests.java | 85 +++++++++++++++++++ ...ConstraintsDSLCompilationServiceTests.java | 65 +++++++++++++- 3 files changed, 151 insertions(+), 2 deletions(-) diff --git a/constraints/src/main/java/gov/nasa/jpl/aerie/constraints/time/Spans.java b/constraints/src/main/java/gov/nasa/jpl/aerie/constraints/time/Spans.java index 90596d66b9..0f918e9c58 100644 --- a/constraints/src/main/java/gov/nasa/jpl/aerie/constraints/time/Spans.java +++ b/constraints/src/main/java/gov/nasa/jpl/aerie/constraints/time/Spans.java @@ -217,7 +217,8 @@ public Spans ends() { @Override public Spans shiftEdges(final Duration fromStart, final Duration fromEnd) { - return this.map($ -> Interval.between($.start.plus(fromStart), $.startInclusivity, $.end.plus(fromEnd), $.endInclusivity)); + return this.map($ -> Interval.between($.start.plus(fromStart), $.startInclusivity, $.end.plus(fromEnd), $.endInclusivity)) + .filter($ -> !$.isEmpty()); } @Override diff --git a/constraints/src/test/java/gov/nasa/jpl/aerie/constraints/tree/ASTTests.java b/constraints/src/test/java/gov/nasa/jpl/aerie/constraints/tree/ASTTests.java index f51289e90c..80196ce03e 100644 --- a/constraints/src/test/java/gov/nasa/jpl/aerie/constraints/tree/ASTTests.java +++ b/constraints/src/test/java/gov/nasa/jpl/aerie/constraints/tree/ASTTests.java @@ -1251,6 +1251,91 @@ public void tesRollingThresholdDeficit() { assertEquals(expected2, result2); } + @Test + void testSpansShiftEdges() { + final var simResults = new SimulationResults( + Instant.EPOCH, Interval.between(0, 20, SECONDS), + List.of(), + Map.of(), + Map.of() + ); + + final var result1 = new ShiftEdges<>( + Supplier.of(new Spans( + Interval.between(0, 1, SECONDS), + Interval.between(0, 2, SECONDS), + Interval.between(0, Inclusive, 2, Exclusive, SECONDS), + Interval.between(0, 3, SECONDS) + )), + Supplier.of(Duration.of(1, SECONDS)), + Supplier.of(Duration.of(-1, SECONDS)) + ).evaluate(simResults); + + final var expected1 = new Spans( + Interval.at(1, SECONDS), + Interval.between(1, 2, SECONDS) + ); + + assertIterableEquals(expected1, result1); + + final var result2 = new ShiftEdges<>( + Supplier.of(new Spans( + Interval.between(0, 1, SECONDS), + Interval.between(0, 2, SECONDS), + Interval.between(0, Inclusive, 2, Exclusive, SECONDS), + Interval.between(0, 3, SECONDS) + )), + Supplier.of(Duration.of(3, SECONDS)), + Supplier.of(Duration.of(4, SECONDS)) + ).evaluate(simResults); + + final var expected2 = new Spans( + Interval.between(3, 5, SECONDS), + Interval.between(3, 6, SECONDS), + Interval.between(3, Inclusive, 6, Exclusive, SECONDS), + Interval.between(3, 7, SECONDS) + ); + + assertIterableEquals(expected2, result2); + } + + @Test + void testSpansSelectWhenTrue() { + final var simResults = new SimulationResults( + Instant.EPOCH, Interval.between(0, 20, SECONDS), + List.of(), + Map.of(), + Map.of() + ); + + final var result = new SpansSelectWhenTrue( + Supplier.of(new Spans( + Interval.between(0, 1, SECONDS), // fully inside + Interval.between(3, 4, SECONDS), // fully outside + Interval.between(5, 7, SECONDS), // half outside + Interval.between(10, 14, SECONDS) // split across multiple + )), + Supplier.of(new Windows(false).set( + List.of( + Interval.between(0, 1, SECONDS), + Interval.between(6, 8, SECONDS), + Interval.between(9, 11, SECONDS), + Interval.between(13, 15, SECONDS) + ), + true + )) + ).evaluate(simResults); + + final var expected = new Spans( + Interval.between(0, 1, SECONDS), + Interval.between(6, 7, SECONDS), + Interval.between(10, 11, SECONDS), + Interval.between(13, 14, SECONDS) + ); + + assertIterableEquals(expected, result); + } + /** * An expression that yields the same aliased object every time it is evaluated. */ diff --git a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsDSLCompilationServiceTests.java b/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsDSLCompilationServiceTests.java index bc5bfc63e6..f291fe4ce2 100644 --- a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsDSLCompilationServiceTests.java +++ b/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsDSLCompilationServiceTests.java @@ -1,5 +1,6 @@ package gov.nasa.jpl.aerie.merlin.server.services; +import gov.nasa.jpl.aerie.constraints.time.Spans; import gov.nasa.jpl.aerie.constraints.tree.AbsoluteInterval; import gov.nasa.jpl.aerie.constraints.time.Interval; import gov.nasa.jpl.aerie.constraints.tree.AccumulatedDuration; @@ -36,6 +37,7 @@ import gov.nasa.jpl.aerie.constraints.tree.ShiftEdges; import gov.nasa.jpl.aerie.constraints.tree.ShorterThan; import gov.nasa.jpl.aerie.constraints.tree.SpansFromWindows; +import gov.nasa.jpl.aerie.constraints.tree.SpansSelectWhenTrue; import gov.nasa.jpl.aerie.constraints.tree.Split; import gov.nasa.jpl.aerie.constraints.tree.Starts; import gov.nasa.jpl.aerie.constraints.tree.Times; @@ -501,7 +503,7 @@ export default() => { return Real.Resource("state of charge").rate().equal(Real.Value(4.0)).shiftBy(minute(2), minute(-20)) } """, - new ViolationsOfWindows(new ShiftEdges( + new ViolationsOfWindows(new ShiftEdges<>( new Equal<>(new Rate(new RealResource("state of charge")), new RealValue(4.0)), new DurationLiteral(Duration.of(2, Duration.MINUTE)), new DurationLiteral(Duration.of(-20, Duration.MINUTE))) @@ -1315,4 +1317,65 @@ export default () => { } } + @Test + void testSpansShiftBy() { + checkSuccessfulCompilation( + """ + const minute = (m: number) => Temporal.Duration.from({minutes: m}); + export default() => { + return Spans.ForEachActivity(ActivityType.activity, i => i.span()).shiftBy(minute(2)).windows(); + } + """, + new ViolationsOfWindows( + new WindowsFromSpans(new ShiftEdges<>( + new ForEachActivitySpans( + "activity", + "span activity alias 0", + new ActivitySpan("span activity alias 0")), + new DurationLiteral(Duration.of(2, Duration.MINUTE)), + new DurationLiteral(Duration.of(2, Duration.MINUTE)))) + ) + ); + + checkSuccessfulCompilation( + """ + const minute = (m: number) => Temporal.Duration.from({minutes: m}); + export default() => { + return Spans.ForEachActivity(ActivityType.activity, i => i.span()).shiftBy(minute(2), minute(3)).windows(); + } + """, + new ViolationsOfWindows( + new WindowsFromSpans(new ShiftEdges<>( + new ForEachActivitySpans( + "activity", + "span activity alias 0", + new ActivitySpan("span activity alias 0")), + new DurationLiteral(Duration.of(2, Duration.MINUTE)), + new DurationLiteral(Duration.of(3, Duration.MINUTE)) + )) + ) + ); + } + + @Test + void testSpansSelectWhenTrue() { + checkSuccessfulCompilation( + """ + const minute = (m: number) => Temporal.Duration.from({minutes: m}); + export default() => { + return Spans.ForEachActivity(ActivityType.activity, i => i.span()).selectWhenTrue(Windows.Value(true)).windows() + } + """, + new ViolationsOfWindows( + new WindowsFromSpans(new SpansSelectWhenTrue( + new ForEachActivitySpans( + "activity", + "span activity alias 0", + new ActivitySpan("span activity alias 0") + ), + new WindowsValue(true) + )) + ) + ); + } }