Skip to content

Commit

Permalink
Refactor for procedural scheduling e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelCourtney committed Sep 13, 2024
1 parent ec30201 commit 2914b7f
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 161 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
- name: Assemble
run: ./gradlew assemble --parallel
- name: Build scheduling procedure jars for testing
run: ./gradlew procedural:examples:foo-procedures:buildAllSchedulingProcedureJars
run: ./gradlew e2e-tests:buildAllSchedulingProcedureJars
- name: Start Services
run: |
docker compose -f ./e2e-tests/docker-compose-test.yml up -d --build
Expand Down
74 changes: 72 additions & 2 deletions e2e-tests/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
id 'java-library'
id 'jacoco'
id 'com.gradleup.shadow' version '8.3.0'
}

java {
Expand Down Expand Up @@ -54,12 +57,17 @@ task e2eTest(type: Test) {
}

dependencies {
testAnnotationProcessor project(':procedural:processor')

testImplementation project(":procedural:scheduling")
testImplementation project(":procedural:timeline")
testImplementation project(':merlin-driver')
testImplementation project(':type-utils')
testImplementation project(':contrib')

testImplementation project(":procedural:remote")
testImplementation "com.zaxxer:HikariCP:5.1.0"
testImplementation("org.postgresql:postgresql:42.6.0")
testImplementation project(':merlin-driver')
testImplementation project(':type-utils')

testImplementation 'com.microsoft.playwright:playwright:1.37.0'

Expand All @@ -69,3 +77,65 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.0'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.0'
}

tasks.register('buildAllSchedulingProcedureJars') {
group = 'SchedulingProcedureJars'

dependsOn "generateSchedulingProcedureJarTasks"
dependsOn {
tasks.findAll { task -> task.name.startsWith('buildSchedulingProcedureJar_') }
}
}

tasks.create("generateSchedulingProcedureJarTasks") {
group = 'SchedulingProcedureJars'

final proceduresDir = findFirstMatchingBuildDir("generated/procedures")

if (proceduresDir == null) {
println "No procedures folder found"
return
}
println "Generating jar tasks for the following procedures directory: ${proceduresDir}"

final files = file(proceduresDir).listFiles()
if (files.length == 0) {
println "No procedures available within folder ${proceduresDir}"
return
}

files.toList().each { file ->
final nameWithoutExtension = file.name.replace(".java", "")
final taskName = "buildSchedulingProcedureJar_${nameWithoutExtension}"

println "Generating ${taskName} task, which will build ${nameWithoutExtension}.jar"

tasks.create(taskName, ShadowJar) {
group = 'SchedulingProcedureJars'
configurations = [project.configurations.testCompileClasspath]
from sourceSets.main.output
archiveBaseName = "" // clear
archiveClassifier.set(nameWithoutExtension) // set output jar name
manifest {
attributes 'Main-Class': getMainClassFromGeneratedFile(file)
}
minimize()
}
}
}

private String findFirstMatchingBuildDir(String pattern) {
String found = null
final generatedDir = file("build/generated/sources")
generatedDir.mkdirs()
generatedDir.eachDirRecurse { dir -> if (dir.path.contains(pattern)) found = dir.path }
return found
}

private static String getMainClassFromGeneratedFile(File file) {
final fileString = file.toString()
final prefix = "build/generated/sources/annotationProcessor/java/main/"
final index = fileString.indexOf(prefix) + prefix.length()
final trimmed = fileString.substring(index).replace(".java", "")
return trimmed.replace("/", ".")
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.microsoft.playwright.Playwright;
import gov.nasa.jpl.aerie.e2e.types.ExternalDataset.ProfileInput;
import gov.nasa.jpl.aerie.e2e.types.ExternalDataset.ProfileInput.ProfileSegmentInput;
import gov.nasa.jpl.aerie.e2e.types.GoalInvocationId;
import gov.nasa.jpl.aerie.e2e.types.Plan;
import gov.nasa.jpl.aerie.e2e.types.ProfileSegment;
import gov.nasa.jpl.aerie.e2e.types.SchedulingRequest.SchedulingStatus;
Expand All @@ -29,7 +28,6 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
Expand All @@ -38,7 +36,7 @@
import static org.junit.jupiter.api.Assertions.fail;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class SchedulingTests {
public class EdslSchedulingTests {
// Requests
private Playwright playwright;
private HasuraRequests hasura;
Expand Down Expand Up @@ -1002,159 +1000,4 @@ void schedulingIgnoreDisabledGoals() throws IOException {
}
}
}

@Nested
class ProceduralSchedulingTests {
private int modelId;
private int planId;
private int specId;
private int procedureJarId;
private GoalInvocationId procedureId;

@BeforeEach
void beforeEach() throws IOException, InterruptedException {
try (final var gateway = new GatewayRequests(playwright)) {
modelId = hasura.createMissionModel(
gateway.uploadJarFile(),
"Banananation (e2e tests)",
"aerie_e2e_tests",
"Proc Scheduling Tests");

procedureJarId = gateway.uploadJarFile("../procedural/examples/foo-procedures/build/libs/SampleProcedure.jar");
}
// Insert the Plan
planId = hasura.createPlan(
modelId,
"Proc Sched Plan - Proc Scheduling Tests",
"48:00:00",
planStartTimestamp);
specId = hasura.getSchedulingSpecId(planId);

// Add Scheduling Procedure
procedureId = hasura.createSchedulingSpecProcedure(
"Test Scheduling Procedure",
procedureJarId,
specId,
0);
}

@AfterEach
void afterEach() throws IOException {
hasura.deleteSchedulingGoal(procedureId.goalId());
hasura.deletePlan(planId);
hasura.deleteMissionModel(modelId);
}

/**
* Upload a procedure jar and add to spec
*/
@Test
void proceduralUploadWorks() throws IOException {
final var ids = hasura.getSchedulingSpecGoalIds(specId);

assertEquals(1, ids.size());
assertEquals(procedureId.goalId(), ids.getFirst());
}

/**
* Run a spec with one procedure in it with required params but no args set
* Should fail scheduling run
*/
@Test
void executeSchedulingRunWithoutArguments() throws IOException {
final var resp = hasura.awaitFailingScheduling(specId);
final var message = resp.reason().getString("message");
assertTrue(message.contains("java.lang.RuntimeException: Record missing key Component[name=quantity"));
}

/**
* Run a spec with one procedure in it
*/
@Test
void executeSchedulingRunWithArguments() throws IOException {
final var args = Json.createObjectBuilder().add("quantity", 2).build();

hasura.updateSchedulingSpecGoalArguments(procedureId.invocationId(), args);

final var resp = hasura.awaitScheduling(specId);

final var plan = hasura.getPlan(planId);
final var activities = plan.activityDirectives();

assertEquals(2, activities.size());

assertTrue(activities.stream().anyMatch(
$ -> Objects.equals($.type(), "BiteBanana") && Objects.equals($.startOffset(), "24:00:00")
));

assertTrue(activities.stream().anyMatch(
$ -> Objects.equals($.type(), "BiteBanana") && Objects.equals($.startOffset(), "30:00:00")
));
}

/**
* Run a spec with two invocations of the same procedure in it
*/
@Test
void executeMultipleInvocationsOfSameProcedure() throws IOException {
final var args = Json.createObjectBuilder().add("quantity", 2).build();
hasura.updateSchedulingSpecGoalArguments(procedureId.invocationId(), args);

final var secondInvocationId = hasura.insertGoalInvocation(procedureId.goalId(), specId);
hasura.updateSchedulingSpecGoalArguments(secondInvocationId.invocationId(), args);

final var resp = hasura.awaitScheduling(specId);

final var plan = hasura.getPlan(planId);
final var activities = plan.activityDirectives();

assertEquals(4, activities.size());
}

/**
* Run a spec with two procedures in it
*/
@Test
void executeMultipleProcedures() throws IOException {
final var args = Json.createObjectBuilder().add("quantity", 2).build();
hasura.updateSchedulingSpecGoalArguments(procedureId.invocationId(), args);

final var secondProcedure = hasura.createSchedulingSpecProcedure(
"Test Scheduling Procedure 2",
procedureJarId,
specId,
1);

hasura.updateSchedulingSpecGoalArguments(secondProcedure.invocationId(), args);

final var resp = hasura.awaitScheduling(specId);

final var plan = hasura.getPlan(planId);
final var activities = plan.activityDirectives();

assertEquals(4, activities.size());
}

/**
* Run a spec with one EDSL goal and one procedure
*/
@Test
void executeEDSLAndProcedure() throws IOException {
final var args = Json.createObjectBuilder().add("quantity", 4).build();
hasura.updateSchedulingSpecGoalArguments(procedureId.invocationId(), args);

final int recurrenceGoalId = hasura.createSchedulingSpecGoal(
"Recurrence Scheduling Test Goal",
recurrenceGoalDefinition,
specId,
1).goalId();

final var resp = hasura.awaitScheduling(specId);

final var plan = hasura.getPlan(planId);
final var activities = plan.activityDirectives();

assertEquals(52, activities.size());
}
}
}
Loading

0 comments on commit 2914b7f

Please sign in to comment.