Skip to content

Commit

Permalink
Add E2E Test
Browse files Browse the repository at this point in the history
- Make Model Upload await logs rather than delay 1.5s
- Fix inconsistency in SchedulingTests.beforeEach
  • Loading branch information
Mythicaeda committed Apr 24, 2024
1 parent ae383db commit 1abfe04
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ void beforeAll() throws IOException, InterruptedException {
"aerie_e2e_tests",
"Mission Model Tests");
}
Thread.sleep(1000);
}

@AfterAll
Expand Down Expand Up @@ -363,4 +362,64 @@ void activityTypesAreUploaded() throws IOException{
assertEquals(expectedComputedAttributes, actualComputedAttributes);
}
}

/**
* The logs for the Hasura events triggered during model upload are accessible.
*/
@Test
void hasuraEventLogsAreAccessible() throws IOException {
final var modelLogs = hasura.awaitModelEventLogs(modelId);

assertEquals(modelId, modelLogs.modelId());
assertEquals("Banananation (e2e tests)", modelLogs.modelName());
assertEquals("Mission Model Tests", modelLogs.modelVersion());

// Check Activity Type Refresh Event Logs
final var activityTypeRefreshLogs = modelLogs.refreshActivityTypesLogs();
assertEquals(1, activityTypeRefreshLogs.size());
final var activityTypeLog = activityTypeRefreshLogs.get(0);

assertEquals("Aerie Legacy", activityTypeLog.triggeringUser());

assertTrue(activityTypeLog.delivered());
assertTrue(activityTypeLog.success());
assertEquals(1, activityTypeLog.tries());
assertEquals(200, activityTypeLog.status());

assertTrue(activityTypeLog.error().isEmpty());
assertTrue(activityTypeLog.errorMessage().isEmpty());
assertTrue(activityTypeLog.errorType().isEmpty());

// Check Model Parameter Refresh Event Logs
final var modelParamRefreshLogs = modelLogs.refreshModelParamsLogs();
assertEquals(1, modelParamRefreshLogs.size());
final var modelParamLog = modelParamRefreshLogs.get(0);

assertEquals("Aerie Legacy", modelParamLog.triggeringUser());

assertTrue(modelParamLog.delivered());
assertTrue(modelParamLog.success());
assertEquals(1, modelParamLog.tries());
assertEquals(200, modelParamLog.status());

assertTrue(modelParamLog.error().isEmpty());
assertTrue(modelParamLog.errorMessage().isEmpty());
assertTrue(modelParamLog.errorType().isEmpty());

// Check Resource Type Refresh Event Logs
final var resourceTypeRefreshLogs = modelLogs.refreshResourceTypesLogs();
assertEquals(1, resourceTypeRefreshLogs.size());
final var resourceTypeLog = resourceTypeRefreshLogs.get(0);

assertEquals("Aerie Legacy", resourceTypeLog.triggeringUser());

assertTrue(resourceTypeLog.delivered());
assertTrue(resourceTypeLog.success());
assertEquals(1, resourceTypeLog.tries());
assertEquals(200, resourceTypeLog.status());

assertTrue(resourceTypeLog.error().isEmpty());
assertTrue(resourceTypeLog.errorMessage().isEmpty());
assertTrue(resourceTypeLog.errorType().isEmpty());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,14 @@ void afterAll() {
}

@BeforeEach
void beforeEach() throws IOException {
void beforeEach() throws IOException, InterruptedException {
// Insert the Mission Model
try (final var gateway = new GatewayRequests(playwright)) {
modelId = hasura.createMissionModel(
gateway.uploadJarFile(),
"Banananation (e2e tests)",
"aerie_e2e_tests",
"Scheduling Tests");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// Insert the Plan
planId = hasura.createPlan(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package gov.nasa.jpl.aerie.e2e.types;

import javax.json.JsonObject;
import java.util.List;
import java.util.Optional;

public record ModelEventLogs(
int modelId,
String modelName,
String modelVersion,
List<EventLog> refreshActivityTypesLogs,
List<EventLog> refreshModelParamsLogs,
List<EventLog> refreshResourceTypesLogs
) {
public record EventLog(
String triggeringUser,
boolean delivered,
boolean success,
int tries,
String createdAt,
int status,
Optional<JsonObject> error,
Optional<String> errorMessage,
Optional<String> errorType
)
{
public static EventLog fromJSON(JsonObject json) {
final Optional<JsonObject> error = json.isNull("error") ?
Optional.empty() : Optional.of(json.getJsonObject("error"));
final Optional<String> errorMsg = json.isNull("error_message") ?
Optional.empty() : Optional.of(json.getString("error_message"));
final Optional<String> errorType = json.isNull("error") ?
Optional.empty() : Optional.of(json.getString("error"));

return new EventLog(
json.getString("triggering_user"),
json.getBoolean("delivered"),
json.getBoolean("success"),
json.getInt("tries"),
json.getString("created_at"),
json.getInt("status"),
error,
errorMsg,
errorType);
}
}

public static ModelEventLogs fromJSON(JsonObject json) {
return new ModelEventLogs(
json.getInt("id"),
json.getString("name"),
json.getString("version"),
json.getJsonArray("refresh_activity_type_logs").getValuesAs(EventLog::fromJSON),
json.getJsonArray("refresh_model_parameter_logs").getValuesAs(EventLog::fromJSON),
json.getJsonArray("refresh_resource_type_logs").getValuesAs(EventLog::fromJSON)
);
}
}
41 changes: 41 additions & 0 deletions e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/utils/GQL.java
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,47 @@ query getExternalDataset($plan_id: Int!, $dataset_id: Int!) {
}
}
}"""),
GET_MODEL_EVENT_LOGS("""
query getModelLogs($modelId: Int!) {
mission_model: mission_model_by_pk(id:$modelId) {
id
name
version
refresh_activity_type_logs(order_by: {created_at: desc}) {
triggering_user
delivered
success
tries
created_at
status
error
error_message
error_type
}
refresh_model_parameter_logs(order_by: {created_at: desc}) {
triggering_user
delivered
success
tries
created_at
status
error
error_message
error_type
}
refresh_resource_type_logs(order_by: {created_at: desc}) {
triggering_user
delivered
success
tries
created_at
status
error
error_message
error_type
}
}
}"""),
GET_PLAN("""
query GetPlan($id: Int!) {
plan: plan_by_pk(id: $id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,12 @@ public int createMissionModel(int jarId, String name, String mission, String ver
.add("version", version);
final var variables = Json.createObjectBuilder().add("model", insertModelBuilder).build();
final var data = makeRequest(GQL.CREATE_MISSION_MODEL, variables).getJsonObject("insert_mission_model_one");
// Delay 1.25s to guarantee all events associated with model upload have finished
final int modelId = data.getInt("id");

// Wait for all events associated with model upload to finish
// Necessary for TS compilation
Thread.sleep(1250);
return data.getInt("id");
awaitModelEventLogs(modelId);
return modelId;
}

public void deleteMissionModel(int id) throws IOException {
Expand Down Expand Up @@ -143,6 +145,39 @@ public List<ActivityType> getActivityTypes(int missionModelId) throws IOExceptio
final var data = makeRequest(GQL.GET_ACTIVITY_TYPES, variables);
return data.getJsonArray("activity_type").getValuesAs(ActivityType::fromJSON);
}

/**
* Get the Hasura Event Logs for the mission model with a timeout of 30 seconds.
* @param modelId the mission model to get logs for
*/
public ModelEventLogs awaitModelEventLogs(int modelId) throws IOException {
return awaitModelEventLogs(modelId, 30);
}

/**
* Get the Hasura Event Logs for the mission model.
* @param modelId the mission model to get logs for
* @param timeout the amount of time to wait for at least one log of each type
*/
public ModelEventLogs awaitModelEventLogs(int modelId, int timeout) throws IOException {
final var variables = Json.createObjectBuilder().add("modelId", modelId).build();

for(int i = 0; i < timeout; ++i){
final var logs = makeRequest(GQL.GET_MODEL_EVENT_LOGS, variables).getJsonObject("mission_model");
if(logs.getJsonArray("refresh_activity_type_logs").isEmpty()
|| logs.getJsonArray("refresh_model_parameter_logs").isEmpty()
|| logs.getJsonArray("refresh_resource_type_logs").isEmpty()) {
try {
Thread.sleep(1000); // 1s
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
return ModelEventLogs.fromJSON(logs);
}
}
throw new TimeoutError("One or more mission model Hausra events did not return after " + timeout + " seconds");
}
//endregion

//region Plan
Expand Down Expand Up @@ -317,7 +352,7 @@ public SimulationResponse awaitSimulation(int planId, int timeout) throws IOExce
throw new TimeoutError("Simulation timed out after " + timeout + " seconds");
}

/**
/**
* Simulate the specified plan, potentially forcibly, with a timeout of 30 seconds
* @param planId the plan to simulate
* @param force whether to forcibly resimulate in the event of an existing dataset.
Expand Down

0 comments on commit 1abfe04

Please sign in to comment.