diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/oir/crud/search.md b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/oir/crud/search.md index e026d4a94a..1e84f460e8 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/oir/crud/search.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/oir/crud/search.md @@ -15,3 +15,10 @@ If it does not, the DSS is failing to implement **[astm.f3548.v21.DSS0005,1](../ ## 🛑 Created operational intent reference is in search results check If the existing operational intent reference is not returned in a search that covers the area it was created for, the DSS is not properly implementing **[astm.f3548.v21.DSS0005,2](../../../../../../../requirements/astm/f3548/v21.md)**. + +## 🛑 Search operational intent reference response contains the expected reference check + +The operational intents returned by a search query and that were created by the test suite are expected to correspond +to what has been created. + +If it does not, the DSS is failing to implement **[astm.f3548.v21.DSS0005,1](../../../../../../../requirements/astm/f3548/v21.md)**. diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/oir/sync.md b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/oir/sync.md index d6623f85e4..0ea2fc59dd 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/oir/sync.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/oir/sync.md @@ -22,6 +22,13 @@ either one of the instances at which the operational intent reference was create If the operational intent reference returned by a DSS to which the operational intent reference was synchronized to does not contain the correct state, either one of the instances at which the operational intent reference was created or the one that was queried, may be failing to implement **[astm.f3548.v21.DSS0210,2d](../../../../../../requirements/astm/f3548/v21.md)**. +## ⚠️ Propagated operational intent reference general area is synchronized check + +When querying a secondary DSS for operational intents in the planning area that contains the propagated operational +intent, if the propagated operational intent is not contained in the response, then the general area in which the +propagated operational intent is located is not synchronized across DSS instances. +As such, either the primary or the secondary DSS fails to properly implements **[astm.f3548.v21.DSS0210,2e](../../../../../../requirements/astm/f3548/v21.md)**. + ## ⚠️ Propagated operational intent reference contains the correct start time check If the operational intent reference returned by a DSS to which the operational intent reference was synchronized to does not contain the correct start time, diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/op_intent_ref_synchronization.md b/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/op_intent_ref_synchronization.md index 4f88a90fe8..13c4d1aaa0 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/op_intent_ref_synchronization.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/op_intent_ref_synchronization.md @@ -55,7 +55,11 @@ Query the created operational intent at every DSS provided in `dss_instances`. #### [Get OIR](../fragments/oir/crud/read.md) -Confirms that each DSS provides access to the created operational intent reference, +Confirms that each DSS provides direct access to the created operational intent reference. + +#### [Search OIR](../fragments/oir/crud/search.md) + +Confirms that each DSS returns the operational intent in relevant search results. #### [OIR is synchronized](../fragments/oir/sync.md) @@ -98,6 +102,10 @@ Confirm that the operational intent reference that was just mutated is properly Confirms that the operational intent reference that was just mutated can be retrieved from any DSS. +#### [Search OIR](../fragments/oir/crud/search.md) + +Confirms that each DSS returns the operational intent in relevant search results. + #### [Validate OIR](../fragments/oir/validate/correctness.md) Verify that the operational intent reference returned by every DSS is correctly formatted and corresponds to what was mutated earlier. diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/op_intent_ref_synchronization.py b/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/op_intent_ref_synchronization.py index a7aa6f53b8..bca81d4717 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/op_intent_ref_synchronization.py +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/op_intent_ref_synchronization.py @@ -1,5 +1,5 @@ from datetime import datetime, timedelta -from typing import List, Optional +from typing import List, Optional, Tuple from implicitdict import StringBasedDateTime from uas_standards.astm.f3548.v21 import api @@ -11,8 +11,10 @@ ) from uas_standards.astm.f3548.v21.constants import Scope +from monitoring.monitorlib import fetch from monitoring.monitorlib.fetch import QueryError from monitoring.monitorlib.geotemporal import Volume4D, Volume4DCollection +from monitoring.monitorlib.temporal import Time from monitoring.prober.infrastructure import register_resource_type from monitoring.uss_qualifier.resources.astm.f3548.v21 import PlanningAreaResource from monitoring.uss_qualifier.resources.astm.f3548.v21.dss import ( @@ -136,6 +138,7 @@ def run(self, context: ExecutionContext): self.begin_test_step("Query newly created OIR") self._query_secondaries_and_compare(self._oir_params) + self._search_secondaries_and_compare(self._oir_params) self.end_test_step() self.begin_test_step("Mutate OIR") @@ -144,6 +147,7 @@ def run(self, context: ExecutionContext): self.begin_test_step("Query updated OIR") self._query_secondaries_and_compare(self._oir_params) + self._search_secondaries_and_compare(self._oir_params) self.end_test_step() self.begin_test_step("Delete OIR") @@ -236,6 +240,83 @@ def _query_secondaries_and_compare( ), ) + def _search_secondaries_and_compare( + self, expected_oir_params: PutOperationalIntentReferenceParameters + ): + for secondary_dss in self._dss_read_instances: + self._validate_area_with_search( + secondary_dss=secondary_dss, + expected_oir_params=expected_oir_params, + involved_participants=list( + {self._primary_pid, secondary_dss.participant_id} + ), + ) + + def _validate_area_with_search( + self, + secondary_dss: DSSInstance, + expected_oir_params: PutOperationalIntentReferenceParameters, + involved_participants: List[str], + ): + # Search for currently active ones in the planning area: + # we expect to find our OIR + oirs, q = self._search_oirs(secondary_dss, self._planning_area_volume4d) + oir_by_id = {oir.id: oir for oir in oirs} + + with self.check( + "Propagated operational intent reference general area is synchronized", + involved_participants, + ) as check: + if self._oir_id not in oir_by_id: + check.record_failed( + summary="Propagated OIR not found", + details=f"OIR {self._oir_id} was not found in the secondary DSS when searched for its expected geo-temporal extent", + query_timestamps=[q.request.timestamp], + ) + + # While we're at it: check the entire search response format and validate the content of the OIR + with self.check( + "Search operational intent reference response contains the expected reference", + involved_participants, + ) as check: + OIRValidator( + main_check=check, + scenario=self, + expected_manager=self._expected_manager, + participant_id=[secondary_dss.participant_id], + oir_params=expected_oir_params, + ).validate_searched_oir( + expected_oir_id=self._oir_id, + search_response=q, + expected_ovn=self._current_oir.ovn, + expected_version=self._current_oir.version, + ) + + # TODO: craft a search with an area of interest that does not intersect with the planning area, + # but whose convex hull intersects with the planning area + + def _search_oirs( + self, secondary_dss: DSSInstance, volume: Volume4D + ) -> Tuple[List[OperationalIntentReference], fetch.Query]: + """Check that the secondaries take the OIR volume into account.""" + # Search for currently active ones in the planning area + with self.check( + "Successful operational intent reference search query", + [secondary_dss.participant_id], + ) as check: + try: + oirs, q = secondary_dss.find_op_intent(volume) + self.record_query(q) + return oirs, q + except QueryError as qe: + self.record_queries(qe.queries) + check.record_failed( + summary="Failed to search for operational intent references", + details=f"Failed to query operational intent references: got response code {qe.last_status_code}: {qe.msg}", + query_timestamps=qe.query_timestamps, + ) + return [], qe.queries[-1] + def _validate_oir_from_secondary( self, secondary_dss: DSSInstance, diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/validators/oir_validator.py b/monitoring/uss_qualifier/scenarios/astm/utm/dss/validators/oir_validator.py index 07566e7fa7..1f604da1e5 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/validators/oir_validator.py +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/validators/oir_validator.py @@ -415,7 +415,7 @@ def validate_searched_oir( QueryOperationalIntentReferenceResponse ) - by_id = {oir: oir.id for oir in resp_parsed.operational_intent_references} + by_id = {oir.id: oir for oir in resp_parsed.operational_intent_references} with self._scenario.check( "Created operational intent reference is in search results", self._pid diff --git a/monitoring/uss_qualifier/suites/astm/utm/dss_probing.md b/monitoring/uss_qualifier/suites/astm/utm/dss_probing.md index 5b0a847279..74db9b71e0 100644 --- a/monitoring/uss_qualifier/suites/astm/utm/dss_probing.md +++ b/monitoring/uss_qualifier/suites/astm/utm/dss_probing.md @@ -27,7 +27,7 @@