diff --git a/.basedpyright/baseline.json b/.basedpyright/baseline.json index b545399a55..977c58c443 100644 --- a/.basedpyright/baseline.json +++ b/.basedpyright/baseline.json @@ -21683,30 +21683,6 @@ "lineCount": 1 } }, - { - "code": "reportPossiblyUnboundVariable", - "range": { - "startColumn": 11, - "endColumn": 31, - "lineCount": 1 - } - }, - { - "code": "reportInvalidTypeVarUse", - "range": { - "startColumn": 14, - "endColumn": 30, - "lineCount": 1 - } - }, - { - "code": "reportPossiblyUnboundVariable", - "range": { - "startColumn": 11, - "endColumn": 31, - "lineCount": 1 - } - }, { "code": "reportInvalidTypeVarUse", "range": { @@ -21714,62 +21690,6 @@ "endColumn": 30, "lineCount": 1 } - }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 59, - "endColumn": 70, - "lineCount": 1 - } - }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 47, - "endColumn": 54, - "lineCount": 1 - } - }, - { - "code": "reportPossiblyUnboundVariable", - "range": { - "startColumn": 15, - "endColumn": 24, - "lineCount": 1 - } - }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 59, - "endColumn": 70, - "lineCount": 1 - } - }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 47, - "endColumn": 54, - "lineCount": 1 - } - }, - { - "code": "reportReturnType", - "range": { - "startColumn": 11, - "endColumn": 20, - "lineCount": 1 - } - }, - { - "code": "reportPossiblyUnboundVariable", - "range": { - "startColumn": 11, - "endColumn": 20, - "lineCount": 1 - } } ], "./monitoring/uss_qualifier/scenarios/astm/utm/versioning/evaluate_system_versions.py": [ diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/availability/sync.md b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/availability/sync.md index 8fd46ecfb0..8563bca23e 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/availability/sync.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/availability/sync.md @@ -1,6 +1,6 @@ # USS Availability Sync test step fragment -## 🛑USS Availability is consistent across every DSS instance check +## 🛑 USS Availability is consistent across every DSS instance check If the reported availability for a USS is not consistent, across a set of DSS instances, with the value that was previously read or set on an arbitrary DSS instance, either the DSS through which the value was set or the one through which the values was retrieved is failing to meet at least one of these requirements: @@ -11,7 +11,7 @@ either the DSS through which the value was set or the one through which the valu As a consequence, the DSS also fails to meet **[astm.f3548.v21.DSS0210,A2-7-2,6](../../../../../../requirements/astm/f3548/v21.md)** and **[astm.f3548.v21.DSS0020](../../../../../../requirements/astm/f3548/v21.md)**. -## 🛑USS Availability version is consistent across every DSS instance check +## 🛑 USS Availability version is consistent across every DSS instance check If the reported availability version for a USS is not consistent, across a set of DSS instances, with the value that was previously read or set on an arbitrary DSS instance, either the DSS through which the value was set or the one through which the values was retrieved is failing to meet at least one of these requirements: diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/availability/update.md b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/availability/update.md index 6b7f48bde0..84892e8db3 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/availability/update.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/availability/update.md @@ -3,7 +3,7 @@ This fragment contains the steps for the USS Availability synchronization scenario where we confirm that a USS availability can be correctly read from a DSS instance -## 🛑USS Availability can be updated check +## 🛑 USS Availability can be updated check If, when presented with a valid query to update the availability state of a USS, a DSS responds with anything else than a 200 OK response, it is in violation of the OpenAPI specification referenced by **[astm.f3548.v21.DSS0100,1](../../../../../../requirements/astm/f3548/v21.md)**. diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/make_dss_report.md b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/report/report.md similarity index 51% rename from monitoring/uss_qualifier/scenarios/astm/utm/make_dss_report.md rename to monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/report/report.md index 5b66df538a..d0e20964b0 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/make_dss_report.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/report/report.md @@ -1,10 +1,10 @@ # Make report to DSS test step fragment This step makes a report to the DSS. -See `make_dss_report` in [test_steps.py](test_steps.py). +See `make_dss_report` in [test_steps_fragments.py](../../test_step_fragments.py). ## 🛑 DSS report successfully submitted check -If the submission of the report to the DSS does not succeed, this check will fail per **[astm.f3548.v21.DSS0100,2](../../../requirements/astm/f3548/v21.md)**. +If the submission of the report to the DSS does not succeed, this check will fail per **[astm.f3548.v21.DSS0100,2](../../../../../../requirements/astm/f3548/v21.md)**. ## ⚠️ DSS returned a valid report ID check -If the ID returned by the DSS is not present or is empty, this check will fail per **[astm.f3548.v21.DSS0100,2](../../../requirements/astm/f3548/v21.md)**. +If the ID returned by the DSS is not present or is empty, this check will fail per **[astm.f3548.v21.DSS0100,2](../../../../../../requirements/astm/f3548/v21.md)**. diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/report.md b/monitoring/uss_qualifier/scenarios/astm/utm/dss/report.md index 109954384a..e64518f5d9 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/report.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/report.md @@ -17,4 +17,4 @@ A dummy `getOperationalIntentReference` query is made to a non-existent DSS in o ### Make valid DSS report test step -#### [Make report to DSS](../make_dss_report.md) +#### [Make report to DSS](./fragments/report/report.md) diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/report.py b/monitoring/uss_qualifier/scenarios/astm/utm/dss/report.py index 54bfc13c47..22e8ec7330 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/report.py +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/report.py @@ -6,7 +6,9 @@ from monitoring.monitorlib.fetch import QueryType, query_and_describe from monitoring.monitorlib.testing import make_fake_url from monitoring.uss_qualifier.resources.astm.f3548.v21.dss import DSSInstanceResource -from monitoring.uss_qualifier.scenarios.astm.utm.test_steps import make_dss_report +from monitoring.uss_qualifier.scenarios.astm.utm.dss.test_step_fragments import ( + make_dss_report, +) from monitoring.uss_qualifier.scenarios.scenario import ( TestScenario, ) @@ -58,5 +60,6 @@ def gen_record() -> ExchangeRecord: self.begin_test_step("Make valid DSS report") dummy_record = gen_record() report_id = make_dss_report(self, self._dss, dummy_record) - self.record_note(f"{self._dss.participant_id}/report_id", report_id) + if report_id: + self.record_note(f"{self._dss.participant_id}/report_id", report_id) self.end_test_step() diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/uss_availability_synchronization.py b/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/uss_availability_synchronization.py index b7a15ff677..6559d63473 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/uss_availability_synchronization.py +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/uss_availability_synchronization.py @@ -8,6 +8,10 @@ DSSInstancesResource, ) from monitoring.uss_qualifier.resources.communications import ClientIdentityResource +from monitoring.uss_qualifier.scenarios.astm.utm.dss.test_step_fragments import ( + get_uss_availability, + set_uss_availability, +) from monitoring.uss_qualifier.scenarios.scenario import TestScenario from monitoring.uss_qualifier.suites.suite import ExecutionContext @@ -145,55 +149,31 @@ def _step_unknown_uss_reported_as_unknown(self): ) def _step_update_to_unknown(self): - with self.check( - "USS Availability can be updated", self._dss.participant_id - ) as check: - try: - self._current_version, q = self._dss.set_uss_availability( - self._uss_id, UssAvailabilityState.Unknown, self._current_version - ) - self.record_query(q) - except QueryError as qe: - self.record_queries(qe.queries) - check.record_failed( - summary="Failed to set USS availability to Unknown", - details=qe.msg, - query_timestamps=qe.query_timestamps, - ) + self._current_version = set_uss_availability( + self, + self._dss, + self._uss_id, + UssAvailabilityState.Unknown, + self._current_version, + ) def _step_update_to_down(self): - with self.check( - "USS Availability can be updated", self._dss.participant_id - ) as check: - try: - self._current_version, q = self._dss.set_uss_availability( - self._uss_id, UssAvailabilityState.Down, self._current_version - ) - self.record_query(q) - except QueryError as qe: - self.record_queries(qe.queries) - check.record_failed( - summary="Failed to set USS availability to Down", - details=qe.msg, - query_timestamps=qe.query_timestamps, - ) + self._current_version = set_uss_availability( + self, + self._dss, + self._uss_id, + UssAvailabilityState.Down, + self._current_version, + ) def _step_update_to_normal(self): - with self.check( - "USS Availability can be updated", self._dss.participant_id - ) as check: - try: - self._current_version, q = self._dss.set_uss_availability( - self._uss_id, UssAvailabilityState.Normal, self._current_version - ) - self.record_query(q) - except QueryError as qe: - self.record_queries(qe.queries) - check.record_failed( - summary="Failed to set USS availability to Normal", - details=qe.msg, - query_timestamps=qe.query_timestamps, - ) + self._current_version = set_uss_availability( + self, + self._dss, + self._uss_id, + UssAvailabilityState.Normal, + self._current_version, + ) def _ensure_test_uss_availability_unknown(self, check_consistency: bool = True): """ @@ -202,27 +182,13 @@ def _ensure_test_uss_availability_unknown(self, check_consistency: bool = True): We want to both start and end this scenario with this state. """ - with self.check( - "USS Availability can be requested", self._dss.participant_id - ) as check: - try: - availability, q = self._dss.get_uss_availability( - self._uss_id, Scope.AvailabilityArbitration - ) - self.record_query(q) - except QueryError as qe: - self.record_queries(qe.queries) - check.record_failed( - summary="Failed to get USS availability", - details=qe.msg, - query_timestamps=qe.query_timestamps, - ) - return - - self._current_version = availability.version + availability, version = get_uss_availability( + self, self._dss, self._uss_id, Scope.AvailabilityArbitration + ) + self._current_version = version # If the state is not currently unknown, we set it to unknown - if availability.status.availability != UssAvailabilityState.Unknown: + if availability != UssAvailabilityState.Unknown: with self.check("USS Availability can be set to Unknown") as check: try: self._current_version, q = self._dss.set_uss_availability( @@ -254,40 +220,27 @@ def _query_and_expect_on_secondary( expected_availability: UssAvailabilityState, expected_version: str, ): - with self.check( - "USS Availability can be requested", dss.participant_id - ) as check: - try: - availability, q = dss.get_uss_availability( - uss_id, Scope.StrategicCoordination - ) - self.record_query(q) - except QueryError as qe: - self.record_queries(qe.queries) - check.record_failed( - summary="Failed to get USS availability", - details=qe.msg, - query_timestamps=qe.query_timestamps, - ) - return + availability, version = get_uss_availability( + self, dss, uss_id, Scope.StrategicCoordination + ) with self.check( "USS Availability is consistent across every DSS instance", participants ) as check: - if availability.status.availability != expected_availability: + if availability != expected_availability: check.record_failed( summary="USS availability not as expected on secondary DSS", - details=f"Expected {expected_availability}, got {availability.status.availability}", + details=f"Expected {expected_availability}, got {availability}", ) with self.check( "USS Availability version is consistent across every DSS instance", participants, ) as check: - if availability.version != expected_version: + if version != expected_version: check.record_failed( summary="USS availability version not as expected on secondary DSS", - details=f"Expected {expected_version}, got {availability.version}", + details=f"Expected {expected_version}, got {version}", ) def _query_and_expect_on_secondaries( diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/test_step_fragments.py b/monitoring/uss_qualifier/scenarios/astm/utm/dss/test_step_fragments.py index d84721fa9a..996018ab61 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/test_step_fragments.py +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/test_step_fragments.py @@ -1,7 +1,10 @@ from uas_standards.astm.f3548.v21.api import ( EntityID, + ExchangeRecord, + UssAvailabilityState, Volume4D, ) +from uas_standards.astm.f3548.v21.constants import Scope from monitoring.monitorlib import fetch from monitoring.monitorlib.fetch import QueryError @@ -331,3 +334,116 @@ def verify_constraint_does_not_exist( summary=f"Constraint intent reference {cr_id} was still found on DSS {dss.participant_id}", details=f"Expected constraint reference {cr_id} to not be found on secondary DSS because it was not present on, or has been removed, from the primary DSS, but it was returned.", ) + + +def get_uss_availability( + scenario: TestScenario, + dss: DSSInstance, + uss_sub: str, + scope: Scope = Scope.StrategicCoordination, +) -> tuple[UssAvailabilityState, str]: + """ + Get the USS availability. + + This function implements the test step fragment described in dss/fragments/availability/read.md. + + Returns: + The state and version of the USS availability. + """ + availability = UssAvailabilityState.Unknown + version = "" + with scenario.check( + "USS Availability can be requested", dss.participant_id + ) as check: + try: + avail_response, avail_query = dss.get_uss_availability(uss_sub, scope) + scenario.record_query(avail_query) + + availability = avail_response.status.availability + version = avail_response.version + except QueryError as e: + scenario.record_queries(e.queries) + avail_query = e.queries[0] + check.record_failed( + summary=f"Availability of USS {uss_sub} could not be requested", + details=f"DSS responded code {avail_query.status_code}; {e}", + query_timestamps=[avail_query.request.timestamp], + ) + return availability, version + + +def set_uss_availability( + scenario: TestScenario, + dss: DSSInstance, + uss_sub: str, + uss_availability: UssAvailabilityState, + version: str = "", +) -> str: + """ + Set the USS availability. + + This function implements the test step fragment described in dss/fragments/availability/update.md. + + Returns: + The new version of the USS availability. + """ + version = "" + with scenario.check( + "USS Availability can be updated", [dss.participant_id] + ) as check: + try: + version, avail_query = dss.set_uss_availability( + uss_sub, + uss_availability, + version, + ) + scenario.record_query(avail_query) + except QueryError as e: + scenario.record_queries(e.queries) + avail_query = e.queries[0] + check.record_failed( + summary=f"Availability of USS {uss_sub} could not be updated to {uss_availability}", + details=f"DSS responded code {avail_query.status_code}; {e}", + query_timestamps=[avail_query.request.timestamp], + ) + return version + + +def make_dss_report( + scenario: TestScenario, + dss: DSSInstance, + exchange: ExchangeRecord, +) -> str | None: + """Make a DSS report. + + This function implements the test step fragment described in dss/fragments/report/report.md. + + Returns: + The report ID. + """ + report_id = None + with scenario.check( + "DSS report successfully submitted", [dss.participant_id] + ) as check: + try: + report_id, report_query = dss.make_report(exchange) + scenario.record_query(report_query) + except QueryError as e: + scenario.record_queries(e.queries) + report_query = e.queries[0] + check.record_failed( + summary="DSS report could not be submitted", + details=f"DSS responded code {report_query.status_code}; {e}", + query_timestamps=[report_query.request.timestamp], + ) + + with scenario.check( + "DSS returned a valid report ID", [dss.participant_id] + ) as check: + if not report_id: + check.record_failed( + summary="Submitted DSS report returned no or empty ID", + details=f"DSS responded code {report_query.status_code} but with no ID for the report", + query_timestamps=[report_query.request.timestamp], + ) + return report_id diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/set_uss_available.md b/monitoring/uss_qualifier/scenarios/astm/utm/set_uss_available.md index 5e9e2e1e45..d3596ab7f0 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/set_uss_available.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/set_uss_available.md @@ -4,5 +4,6 @@ This step sets the USS availability to 'Available' at the DSS. See `set_uss_available` in [test_steps.py](test_steps.py). -## 🛑 USS availability successfully set to 'Available' check -**[astm.f3548.v21.DSS0100,1](../../../requirements/astm/f3548/v21.md)** +## [Availability can be read](./dss/fragments/availability/read.md) + +## [Availability can be updated](./dss/fragments/availability/update.md) diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/set_uss_down.md b/monitoring/uss_qualifier/scenarios/astm/utm/set_uss_down.md index 401b9b65d8..546ddf29b2 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/set_uss_down.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/set_uss_down.md @@ -4,5 +4,6 @@ This step sets the USS availability to 'Down' at the DSS. See `set_uss_down` in [test_steps.py](test_steps.py). -## 🛑 USS availability successfully set to 'Down' check -**[astm.f3548.v21.DSS0100,1](../../../requirements/astm/f3548/v21.md)** +## [Availability can be read](./dss/fragments/availability/read.md) + +## [Availability can be updated](./dss/fragments/availability/update.md) diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/test_steps.py b/monitoring/uss_qualifier/scenarios/astm/utm/test_steps.py index e952024ee8..d5eace6db2 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/test_steps.py +++ b/monitoring/uss_qualifier/scenarios/astm/utm/test_steps.py @@ -5,7 +5,6 @@ from implicitdict import ImplicitDict from uas_standards.astm.f3548.v21.api import ( EntityID, - ExchangeRecord, GetOperationalIntentDetailsResponse, OperationalIntentReference, OperationalIntentState, @@ -24,6 +23,10 @@ from monitoring.monitorlib.fetch import QueryError from monitoring.monitorlib.geotemporal import Volume4DCollection from monitoring.uss_qualifier.resources.astm.f3548.v21.dss import DSSInstance +from monitoring.uss_qualifier.scenarios.astm.utm.dss.test_step_fragments import ( + get_uss_availability, + set_uss_availability, +) from monitoring.uss_qualifier.scenarios.astm.utm.evaluation import ( validate_op_intent_details, ) @@ -650,100 +653,19 @@ def set_uss_available( scenario: TestScenarioType, dss: DSSInstance, uss_sub: str, -) -> str: - """Set the USS availability to 'Available'. - - This function implements the test step fragment described in set_uss_available.md. - - Returns: - The new version of the USS availability. - """ - with scenario.check( - "USS availability successfully set to 'Available'", [dss.participant_id] - ) as check: - try: - availability_version, avail_query = dss.set_uss_availability( - uss_sub, - UssAvailabilityState.Normal, - ) - scenario.record_query(avail_query) - except QueryError as e: - scenario.record_queries(e.queries) - avail_query = e.queries[0] - check.record_failed( - summary=f"Availability of USS {uss_sub} could not be set to available", - details=f"DSS responded code {avail_query.status_code}; {e}", - query_timestamps=[avail_query.request.timestamp], - ) - return availability_version +): + _, version = get_uss_availability( + scenario, dss, uss_sub, Scope.AvailabilityArbitration + ) + set_uss_availability(scenario, dss, uss_sub, UssAvailabilityState.Normal, version) def set_uss_down( scenario: TestScenarioType, dss: DSSInstance, uss_sub: str, -) -> str: - """Set the USS availability to 'Down'. - - This function implements the test step fragment described in set_uss_down.md. - - Returns: - The new version of the USS availability. - """ - with scenario.check( - "USS availability successfully set to 'Down'", [dss.participant_id] - ) as check: - try: - availability_version, avail_query = dss.set_uss_availability( - uss_sub, - UssAvailabilityState.Down, - ) - scenario.record_query(avail_query) - except QueryError as e: - scenario.record_queries(e.queries) - avail_query = e.queries[0] - check.record_failed( - summary=f"Availability of USS {uss_sub} could not be set to down", - details=f"DSS responded code {avail_query.status_code}; {e}", - query_timestamps=[avail_query.request.timestamp], - ) - return availability_version - - -def make_dss_report( - scenario: TestScenarioType, - dss: DSSInstance, - exchange: ExchangeRecord, -) -> str: - """Make a DSS report. - - This function implements the test step fragment described in make_dss_report.md. - - Returns: - The report ID. - """ - with scenario.check( - "DSS report successfully submitted", [dss.participant_id] - ) as check: - try: - report_id, report_query = dss.make_report(exchange) - scenario.record_query(report_query) - except QueryError as e: - scenario.record_queries(e.queries) - report_query = e.cause - check.record_failed( - summary="DSS report could not be submitted", - details=f"DSS responded code {report_query.status_code}; {e}", - query_timestamps=[report_query.request.timestamp], - ) - - with scenario.check( - "DSS returned a valid report ID", [dss.participant_id] - ) as check: - if not report_id: - check.record_failed( - summary="Submitted DSS report returned no or empty ID", - details=f"DSS responded code {report_query.status_code} but with no ID for the report", - query_timestamps=[report_query.request.timestamp], - ) - return report_id +): + _, version = get_uss_availability( + scenario, dss, uss_sub, Scope.AvailabilityArbitration + ) + set_uss_availability(scenario, dss, uss_sub, UssAvailabilityState.Down, version)