diff --git a/backend/migrations/versions/2024_06_11_2002-2745d4e5bc72_create_test_status_update_tables.py b/backend/migrations/versions/2024_06_11_2002-2745d4e5bc72_create_test_status_update_tables.py index 7009873b..5c112e11 100644 --- a/backend/migrations/versions/2024_06_11_2002-2745d4e5bc72_create_test_status_update_tables.py +++ b/backend/migrations/versions/2024_06_11_2002-2745d4e5bc72_create_test_status_update_tables.py @@ -42,7 +42,7 @@ def upgrade() -> None: ) with op.get_context().autocommit_block(): - op.execute("ALTER TYPE testexecutionstatus ADD VALUE 'ENDED'") + op.execute("ALTER TYPE testexecutionstatus ADD VALUE 'ENDED_PREMATURELY'") def downgrade() -> None: diff --git a/backend/test_observer/controllers/test_executions/status_update.py b/backend/test_observer/controllers/test_executions/status_update.py index ee98643c..25324594 100644 --- a/backend/test_observer/controllers/test_executions/status_update.py +++ b/backend/test_observer/controllers/test_executions/status_update.py @@ -58,11 +58,11 @@ def put_status_update( if event_parser.resource_url is not None: test_execution.resource_url = event_parser.resource_url if ( - event_parser.is_completed + event_parser.is_ended_prematurely and test_execution.status is not TestExecutionStatus.FAILED and test_execution.status is not TestExecutionStatus.PASSED ): - test_execution.status = TestExecutionStatus.ENDED + test_execution.status = TestExecutionStatus.ENDED_PREMATURELY db.commit() diff --git a/backend/test_observer/controllers/test_executions/testflinger_event_parser.py b/backend/test_observer/controllers/test_executions/testflinger_event_parser.py index c01bc5f6..9f34a530 100644 --- a/backend/test_observer/controllers/test_executions/testflinger_event_parser.py +++ b/backend/test_observer/controllers/test_executions/testflinger_event_parser.py @@ -19,12 +19,12 @@ class TestflingerEventParser: def __init__(self): - self.is_completed = False + self.is_ended_prematurely = False self.resource_url = None def process_events(self, events: list[TestEvent]): final_event = events[-1] - if final_event.event_name == "job_end": - self.is_completed = True + if final_event.event_name == "job_end" and final_event.detail != "normal_exit": + self.is_ended_prematurely = True if events[0].event_name == "job_start": self.resource_url = events[0].detail diff --git a/backend/test_observer/data_access/models_enums.py b/backend/test_observer/data_access/models_enums.py index 8f3e63e9..75458c8c 100644 --- a/backend/test_observer/data_access/models_enums.py +++ b/backend/test_observer/data_access/models_enums.py @@ -35,7 +35,7 @@ class TestExecutionStatus(str, Enum): PASSED = "PASSED" FAILED = "FAILED" NOT_TESTED = "NOT_TESTED" - ENDED = "ENDED" + ENDED_PREMATURELY = "ENDED_PREMATURELY" class TestExecutionReviewDecision(str, Enum): diff --git a/backend/tests/controllers/test_executions/test_status_update.py b/backend/tests/controllers/test_executions/test_status_update.py index 7cd714c9..fb878f01 100644 --- a/backend/tests/controllers/test_executions/test_status_update.py +++ b/backend/tests/controllers/test_executions/test_status_update.py @@ -64,7 +64,7 @@ def test_status_updates_stored(test_client: TestClient, generator: DataGenerator "2015-03-21T11:08:15.859831" ) assert test_execution.test_events[1].detail == "my_detail_two" - assert test_execution.status == "ENDED" + assert test_execution.status == "ENDED_PREMATURELY" def test_status_updates_is_idempotent( @@ -176,3 +176,38 @@ def test_status_updates_invalid_timestamp( }, ) assert response.status_code == 422 + + +def test_status_update_normal_exit(test_client: TestClient, generator: DataGenerator): + artefact = generator.gen_artefact("beta") + artefact_build = generator.gen_artefact_build(artefact) + environment = generator.gen_environment() + test_execution = generator.gen_test_execution( + artefact_build, environment, ci_link="http://localhost" + ) + + test_client.put( + f"/v1/test-executions/{test_execution.id}/status_update", + json={ + "agent_id": "test_agent", + "job_queue": "test_job_queue", + "events": [ + { + "event_name": "started_setup", + "timestamp": "201-03-21T11:08:14.859831", + "detail": "my_detail_one", + }, + { + "event_name": "ended_setup", + "timestamp": "20-03-21T11:08:15.859831", + "detail": "my_detail_two", + }, + { + "event_name": "job_end", + "timestamp": "2015-03-21T11:08:15.859831", + "detail": "normal_exit", + }, + ], + }, + ) + assert test_execution.status != "ENDED_PREMATURELY" diff --git a/frontend/lib/models/test_execution.dart b/frontend/lib/models/test_execution.dart index 050645fd..a0249be5 100644 --- a/frontend/lib/models/test_execution.dart +++ b/frontend/lib/models/test_execution.dart @@ -51,15 +51,15 @@ enum TestExecutionStatus { inProgress, @JsonValue('PASSED') passed, - @JsonValue('ENDED') - ended; + @JsonValue('ENDED_PREMATURELY') + endedPrematurely; bool get isCompleted { switch (this) { case notStarted: case inProgress: case notTested: - case ended: + case endedPrematurely: return false; case passed: case failed: @@ -79,8 +79,8 @@ enum TestExecutionStatus { return 'Failed'; case notTested: return 'Not Tested'; - case ended: - return 'Ended'; + case endedPrematurely: + return 'Ended Prematurely'; } } @@ -97,7 +97,7 @@ enum TestExecutionStatus { return const Icon(YaruIcons.error, color: YaruColors.red, size: size); case notTested: return const Icon(YaruIcons.information, size: size); - case ended: + case endedPrematurely: return const Icon(YaruIcons.junk_filled, size: size); } } diff --git a/frontend/lib/ui/artefact_page/test_result_filter_expandable.dart b/frontend/lib/ui/artefact_page/test_result_filter_expandable.dart index 0417ce61..9c15882e 100644 --- a/frontend/lib/ui/artefact_page/test_result_filter_expandable.dart +++ b/frontend/lib/ui/artefact_page/test_result_filter_expandable.dart @@ -51,7 +51,7 @@ class TestResultsFilterExpandable extends ConsumerWidget { ), children: filteredTestResults .map( - (testResult) => TestResultExpandable(testResult: testResult), + (testResult) => TestResultExpandable(testResult: testResult), ) .toList(), );