From 9510d24e43ecda8a711c95dc82ebfa1d6b95e1d3 Mon Sep 17 00:00:00 2001 From: pranav-super Date: Wed, 23 Oct 2024 11:23:55 -0700 Subject: [PATCH] finish tests --- .../procedures/ExternalEventsQueryGoal.java | 31 ++++ ...oal.java => ExternalEventsSimpleGoal.java} | 5 +- .../scheduling/ExternalEventsTests.java | 164 ++++++++++++++---- .../jpl/aerie/e2e/utils/HasuraRequests.java | 2 +- .../procedural/timeline/plan/EventQuery.kt | 8 +- .../aerie/procedural/timeline/plan/Plan.kt | 2 +- .../plan/SchedulerToProcedurePlanAdapter.kt | 2 +- 7 files changed, 169 insertions(+), 45 deletions(-) create mode 100644 e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsQueryGoal.java rename e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/{ExternalEventsGoal.java => ExternalEventsSimpleGoal.java} (86%) diff --git a/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsQueryGoal.java b/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsQueryGoal.java new file mode 100644 index 0000000000..dcd3644786 --- /dev/null +++ b/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsQueryGoal.java @@ -0,0 +1,31 @@ +package gov.nasa.jpl.aerie.e2e.procedural.scheduling.procedures; + +import gov.nasa.ammos.aerie.procedural.scheduling.Goal; +import gov.nasa.ammos.aerie.procedural.scheduling.annotations.SchedulingProcedure; +import gov.nasa.ammos.aerie.procedural.scheduling.plan.EditablePlan; +import gov.nasa.ammos.aerie.procedural.timeline.payloads.activities.DirectiveStart; +import gov.nasa.ammos.aerie.procedural.timeline.plan.EventQuery; +import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; + +@SchedulingProcedure +public record ExternalEventsQueryGoal() implements Goal { + @Override + public void run(@NotNull final EditablePlan plan) { + + // demonstrate more complicated query functionality + EventQuery eventQuery = new EventQuery( + List.of("TestGroup", "TestGroup_2"), + List.of("TestType"), + null + ); + + for (final var e: plan.events(eventQuery)) { + plan.create("BiteBanana", new DirectiveStart.Absolute(e.getInterval().start), Map.of("biteSize", SerializedValue.of(1))); + } + plan.commit(); + } +} diff --git a/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsGoal.java b/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsSimpleGoal.java similarity index 86% rename from e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsGoal.java rename to e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsSimpleGoal.java index 2657a3355c..216cd3faae 100644 --- a/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsGoal.java +++ b/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsSimpleGoal.java @@ -10,13 +10,12 @@ import java.util.Map; @SchedulingProcedure -public record ExternalEventsGoal() implements Goal { +public record ExternalEventsSimpleGoal() implements Goal { @Override public void run(@NotNull final EditablePlan plan) { - for (final var e: plan.events("Derivation Test Default")) { + for (final var e: plan.events("TestGroup")) { plan.create("BiteBanana", new DirectiveStart.Absolute(e.getInterval().start), Map.of("biteSize", SerializedValue.of(1))); } - plan.commit(); } } diff --git a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/ExternalEventsTests.java b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/ExternalEventsTests.java index d3e984598a..db3de04e7f 100644 --- a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/ExternalEventsTests.java +++ b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/ExternalEventsTests.java @@ -1,32 +1,37 @@ package gov.nasa.jpl.aerie.e2e.procedural.scheduling; -import gov.nasa.jpl.aerie.e2e.ExternalDatasetsTest; import gov.nasa.jpl.aerie.e2e.types.GoalInvocationId; +import gov.nasa.jpl.aerie.e2e.types.Plan; import gov.nasa.jpl.aerie.e2e.utils.GatewayRequests; import gov.nasa.jpl.aerie.e2e.utils.HasuraRequests; +import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import javax.json.JsonArray; import java.io.IOException; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Comparator; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class ExternalEventsTests extends ProceduralSchedulingSetup { private GoalInvocationId procedureId; - private int datasetId; - private final static String SOURCE_TYPE = "TestType"; private final static String EVENT_TYPE = "TestType"; + private final static String ADDITIONAL_EVENT_TYPE = EVENT_TYPE + "_2"; private final static String DERIVATION_GROUP = "TestGroup"; + private final static String ADDITIONAL_DERIVATION_GROUP = DERIVATION_GROUP + "_2"; private final HasuraRequests.ExternalSource externalSource = new HasuraRequests.ExternalSource( "Test.json", SOURCE_TYPE, DERIVATION_GROUP, "2024-01-01T00:00:00Z", - "2024-01-01T00:00:00Z", - "2024-01-08T00:00:00Z", + "2023-01-01T00:00:00Z", + "2023-01-08T00:00:00Z", "2024-10-01T00:00:00Z" ); private final List externalEvents = List.of( @@ -35,7 +40,7 @@ public class ExternalEventsTests extends ProceduralSchedulingSetup { EVENT_TYPE, externalSource.key(), externalSource.derivation_group_name(), - "2024-01-01T01:00:00Z", + "2023-01-01T01:00:00Z", "00:10:00" ), new HasuraRequests.ExternalEvent( @@ -43,7 +48,7 @@ public class ExternalEventsTests extends ProceduralSchedulingSetup { EVENT_TYPE, externalSource.key(), externalSource.derivation_group_name(), - "2024-01-01T03:00:00Z", + "2023-01-01T03:00:00Z", "00:10:00" ), new HasuraRequests.ExternalEvent( @@ -51,64 +56,153 @@ public class ExternalEventsTests extends ProceduralSchedulingSetup { EVENT_TYPE, externalSource.key(), externalSource.derivation_group_name(), - "2024-01-01T05:00:00Z", + "2023-01-01T05:00:00Z", "00:10:00" ) ); - @BeforeEach - void localBeforeEach() throws IOException { - try (final var gateway = new GatewayRequests(playwright)) { - int procedureJarId = gateway.uploadJarFile("build/libs/ExternalEventsGoal.jar"); - // Add Scheduling Procedure - procedureId = hasura.createSchedulingSpecProcedure( - "Test Scheduling Procedure", - procedureJarId, - specId, - 0 - ); + private final HasuraRequests.ExternalSource additionalExternalSource = new HasuraRequests.ExternalSource( + "NewTest.json", + SOURCE_TYPE, + ADDITIONAL_DERIVATION_GROUP, + "2024-01-02T00:00:00Z", + "2023-01-01T00:00:00Z", + "2023-01-08T00:00:00Z", + "2024-10-01T00:00:00Z" + ); - datasetId = hasura.insertExternalDataset( - planId, - "2023-001T01:00:00.000", - List.of(ExternalDatasetsTest.myBooleanProfile) - ); - } + private final List additionalExternalEvents = List.of( + new HasuraRequests.ExternalEvent( + "Event_01", + EVENT_TYPE, + additionalExternalSource.key(), + additionalExternalSource.derivation_group_name(), + "2023-01-02T01:00:00Z", + "00:10:00" + ), + new HasuraRequests.ExternalEvent( + "Event_02", + ADDITIONAL_EVENT_TYPE, + additionalExternalSource.key(), + additionalExternalSource.derivation_group_name(), + "2023-01-02T03:00:00Z", + "00:10:00" + ), + new HasuraRequests.ExternalEvent( + "Event_03", + ADDITIONAL_EVENT_TYPE, + additionalExternalSource.key(), + additionalExternalSource.derivation_group_name(), + "2023-01-02T05:00:00Z", + "00:10:00" + ) + ); + @BeforeEach + void localBeforeEach() throws IOException { // Upload some External Events (and associated infrastructure) hasura.insertExternalSourceType(SOURCE_TYPE); hasura.insertExternalEventType(EVENT_TYPE); hasura.insertDerivationGroup(DERIVATION_GROUP, SOURCE_TYPE); hasura.insertExternalSource(externalSource); hasura.insertExternalEvents(externalEvents); - - // Note: we do not need to manually delete this. The plan is deleted first in ProceduralSchedulingSetup.java's - // @AfterEach method, which cascades and deletes this. Attempting deletion will cause error. hasura.insertPlanDerivationGroupAssociation(planId, DERIVATION_GROUP); + + // Upload additional External Events in a different derivation group and of a different type + hasura.insertExternalEventType(ADDITIONAL_EVENT_TYPE); + hasura.insertDerivationGroup(ADDITIONAL_DERIVATION_GROUP, SOURCE_TYPE); + hasura.insertExternalSource(additionalExternalSource); + hasura.insertExternalEvents(additionalExternalEvents); + hasura.insertPlanDerivationGroupAssociation(planId, ADDITIONAL_DERIVATION_GROUP); } @AfterEach void localAfterEach() throws IOException { hasura.deleteSchedulingGoal(procedureId.goalId()); - hasura.deleteExternalDataset(planId, datasetId); // External Event Related - hasura.deletePlanDerivationGroup(planId, DERIVATION_GROUP); + hasura.deletePlanDerivationGroupAssociation(planId, DERIVATION_GROUP); + hasura.deletePlanDerivationGroupAssociation(planId, ADDITIONAL_DERIVATION_GROUP); hasura.deleteExternalSource(externalSource); + hasura.deleteExternalSource(additionalExternalSource); hasura.deleteDerivationGroup(DERIVATION_GROUP); + hasura.deleteDerivationGroup(ADDITIONAL_DERIVATION_GROUP); hasura.deleteExternalSourceType(SOURCE_TYPE); hasura.deleteExternalEventType(EVENT_TYPE); + hasura.deleteExternalEventType(ADDITIONAL_EVENT_TYPE); } @Test - void testExternalEventQuery() throws IOException { + void testExternalEventSimple() throws IOException { + // first, run the goal + try (final var gateway = new GatewayRequests(playwright)) { + int procedureJarId = gateway.uploadJarFile("build/libs/ExternalEventsSimpleGoal.jar"); + // Add Scheduling Procedure + procedureId = hasura.createSchedulingSpecProcedure( + "Test Scheduling Procedure", + procedureJarId, + specId, + 0 + ); + } hasura.awaitScheduling(specId); - final var plan = hasura.getPlan(planId); final var activities = plan.activityDirectives(); - // TODO pranav make sure the ExternalEventsGoal successfully made Bite Banana activities one-to-one with the uploaded events. + // ensure the order lines up with the events' + activities.sort(Comparator.comparing(Plan.ActivityDirective::startOffset)); + + // compare arrays + assertEquals(externalEvents.size(), activities.size()); + for (int i = 0; i < activities.size(); i++) { + Instant activityStartTime = Duration.addToInstant( + Instant.parse(planStartTimestamp), + Duration.fromString(activities.get(i).startOffset()) + ); + assertEquals(externalEvents.get(i).start_time(), activityStartTime.toString()); + } } - // TODO pranav add another goal that filters by type and group, test it here + @Test + void testExternalEventQuery() throws IOException { + // first, run the goal + try (final var gateway = new GatewayRequests(playwright)) { + int procedureJarId = gateway.uploadJarFile("build/libs/ExternalEventsQueryGoal.jar"); + // Add Scheduling Procedure + procedureId = hasura.createSchedulingSpecProcedure( + "Test Scheduling Procedure", + procedureJarId, + specId, + 0 + ); + } + hasura.awaitScheduling(specId); + final var plan = hasura.getPlan(planId); + final var activities = plan.activityDirectives(); + + // ensure the orderings line up + activities.sort(Comparator.comparing(Plan.ActivityDirective::startOffset)); + + // get the set of events we expect (anything in TestGroup or TestGroup_2, and of type TestType) + List expected = new ArrayList<>(); + expected.addAll(externalEvents); + expected.addAll( + additionalExternalEvents.stream() + .filter(e -> e.event_type_name().equals(EVENT_TYPE)) + .toList() + ); + + // explicitly ensure the orderings line up + expected.sort(Comparator.comparing(HasuraRequests.ExternalEvent::start_time)); + + // compare arrays + assertEquals(expected.size(), activities.size()); + for (int i = 0; i < activities.size(); i++) { + Instant activityStartTime = Duration.addToInstant( + Instant.parse(planStartTimestamp), + Duration.fromString(activities.get(i).startOffset()) + ); + assertEquals(activityStartTime.toString(), expected.get(i).start_time()); + } + } } diff --git a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/utils/HasuraRequests.java b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/utils/HasuraRequests.java index b1cbe797ed..71b5dff661 100644 --- a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/utils/HasuraRequests.java +++ b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/utils/HasuraRequests.java @@ -1126,7 +1126,7 @@ public String deleteExternalSource( .getJsonObject("deleteExternalSource") .getString("key"); } - public String deletePlanDerivationGroup( + public String deletePlanDerivationGroupAssociation( int planId, String derivationGroupName ) throws IOException { diff --git a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/EventQuery.kt b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/EventQuery.kt index f88033fc85..a9c80c4be1 100644 --- a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/EventQuery.kt +++ b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/EventQuery.kt @@ -10,11 +10,11 @@ data class EventQuery( val derivationGroups: List?, /** - * A nullable list of types; the event must belong to one of them if present. + * A nullable list of eventTypes; the event must belong to one of them if present. * * If null, all types are allowed. */ - val types: List?, + val eventTypes: List?, /** * A nullable list of sources; the event must belong to one of them if present. @@ -23,9 +23,9 @@ data class EventQuery( */ val sources: List?, ) { - constructor(derivationGroup: String?, type: String?, source: String?): this( + constructor(derivationGroup: String?, eventType: String?, source: String?): this( derivationGroup?.let { listOf(it) }, - type?.let { listOf(it) }, + eventType?.let { listOf(it) }, source?.let { listOf(it) } ) constructor(): this(null as String?, null, null) diff --git a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/Plan.kt b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/Plan.kt index b9e3c024ca..0839384d52 100644 --- a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/Plan.kt +++ b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/Plan.kt @@ -46,7 +46,7 @@ interface Plan { /** Get external events associated with this plan. */ fun events(query: EventQuery): ExternalEvents /** Get external events belonging to a given derivation group and external event type associated with this plan. */ - fun events(derivationGroup: String, type: String) = events(EventQuery(derivationGroup, type, null)) + fun events(derivationGroup: String, eventType: String) = events(EventQuery(derivationGroup, eventType, null)) /** Get external events belonging to a given derivation group associated with this plan. */ fun events(derivationGroup: String) = events(EventQuery(derivationGroup, null, null)) /** Get all external events across all derivation groups associated with this plan. */ diff --git a/scheduler-driver/src/main/kotlin/gov/nasa/jpl/aerie/scheduler/plan/SchedulerToProcedurePlanAdapter.kt b/scheduler-driver/src/main/kotlin/gov/nasa/jpl/aerie/scheduler/plan/SchedulerToProcedurePlanAdapter.kt index 3e7f979374..c23b5cbdbc 100644 --- a/scheduler-driver/src/main/kotlin/gov/nasa/jpl/aerie/scheduler/plan/SchedulerToProcedurePlanAdapter.kt +++ b/scheduler-driver/src/main/kotlin/gov/nasa/jpl/aerie/scheduler/plan/SchedulerToProcedurePlanAdapter.kt @@ -65,7 +65,7 @@ data class SchedulerToProcedurePlanAdapter( ?: throw Error("derivation group either doesn't exist or isn't associated with plan: $it") } else eventsByDerivationGroup.values.flatten() - if (query.types != null) result = result.filter { it.type in query.types!! } + if (query.eventTypes != null) result = result.filter { it.type in query.eventTypes!! } if (query.sources != null) result = result.filter { it.source in query.sources!! } return ExternalEvents(result) }