diff --git a/monitoring/prober/infrastructure.py b/monitoring/prober/infrastructure.py index 8e644f3400..f90115ff5b 100644 --- a/monitoring/prober/infrastructure.py +++ b/monitoring/prober/infrastructure.py @@ -100,7 +100,7 @@ def wrapper_default_scope(*args, **kwargs): resource_type_code_descriptions: Dict[ResourceType, str] = {} -# Next code: 369 +# Next code: 372 def register_resource_type(code: int, description: str) -> ResourceType: """Register that the specified code refers to the described resource. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_expiry.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_expiry.py new file mode 100644 index 0000000000..6debc0c44f --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_expiry.py @@ -0,0 +1,143 @@ +import datetime +import time +from typing import Optional + +import arrow +from uas_standards.astm.f3411 import v19, v22a + +from monitoring.monitorlib.rid import RIDVersion +from monitoring.prober.infrastructure import register_resource_type +from monitoring.uss_qualifier.common_data_definitions import Severity +from monitoring.uss_qualifier.resources.astm.f3411.dss import DSSInstanceResource +from monitoring.uss_qualifier.resources.interuss.id_generator import IDGeneratorResource +from monitoring.uss_qualifier.resources.netrid.service_area import ServiceAreaResource +from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss import utils +from monitoring.uss_qualifier.scenarios.astm.netrid.dss_wrapper import DSSWrapper +from monitoring.uss_qualifier.scenarios.scenario import GenericTestScenario + + +class ISAExpiry(GenericTestScenario): + """Based on test_isa_expiry.py from the legacy prober tool.""" + + ISA_TYPE = register_resource_type(369, "ISA") + + create_isa_path: str + + write_scope: str + + def __init__( + self, + dss: DSSInstanceResource, + id_generator: IDGeneratorResource, + isa: ServiceAreaResource, + ): + super().__init__() + self._dss = ( + dss.dss_instance + ) # TODO: delete once _delete_isa_if_exists updated to use dss_wrapper + self._dss_wrapper = DSSWrapper(self, dss.dss_instance) + self._isa_id = id_generator.id_factory.make_id(ISAExpiry.ISA_TYPE) + self._isa_version: Optional[str] = None + self._isa = isa.specification + + now = arrow.utcnow().datetime + self._isa_start_time = self._isa.shifted_time_start(now) + self._isa_end_time = self._isa.shifted_time_end(now) + self._isa_area = [vertex.as_s2sphere() for vertex in self._isa.footprint] + + def run(self): + self.begin_test_scenario() + + self._setup_case() + + self.begin_test_case("ISA Expiry") + self.begin_test_step("ISA Expiry") + + self._check_expiry_behaviors() + + self.end_test_step() + self.end_test_case() + self.end_test_scenario() + + def _check_expiry_behaviors(self): + """ + Once an ISA is expired, it may still be queried directly using its ID, + but it should not appear in searches anymore. + """ + + start_time = datetime.datetime.utcnow() + end_time = start_time + datetime.timedelta(seconds=5) + + # Create a short lived ISA of a few seconds + with self.check("Create short lived ISA", [self._dss.participant_id]) as check: + created_isa = self._dss_wrapper.put_isa_expect_response_code( + check=check, + expected_error_codes={200}, + area_vertices=self._isa_area, + alt_lo=self._isa.altitude_min, + alt_hi=self._isa.altitude_max, + start_time=start_time, + end_time=end_time, + uss_base_url=self._isa.base_url, + isa_id=self._isa_id, + isa_version=None, + ) + + # Wait for it to expire + time.sleep(5) + + # Search for ISAs: we should not find the expired one + with self.check( + "Expired ISAs are not part of search results", [self._dss.participant_id] + ) as check: + isas = self._dss_wrapper.search_isas_expect_response_code( + main_check=check, + expected_error_codes={200}, + area=self._isa_area, + ) + if self._isa_id in isas.isas.keys(): + check.record_failed( + summary=f"Expired ISA {self._isa_id} found in search results", + severity=Severity.Medium, + participants=[self._dss.participant_id], + details=f"Searched for area {self._isa_area} with unspecified end and start time.", + query_timestamps=[ + created_isa.dss_query.query.request.timestamp, + isas.query.request.timestamp, + ], + ) + + with self.check( + "An expired ISA can be queried by its ID", [self._dss.participant_id] + ) as check: + self._dss_wrapper.get_isa(check, self._isa_id) + + def _setup_case(self): + self.begin_test_case("Setup") + + def _ensure_clean_workspace_step(): + self.begin_test_step("Ensure clean workspace") + + self._delete_isa_if_exists() + + self.end_test_step() + + _ensure_clean_workspace_step() + + self.end_test_case() + + def _delete_isa_if_exists(self): + utils.delete_isa_if_exists( + self, + isa_id=self._isa_id, + rid_version=self._dss.rid_version, + session=self._dss.client, + server_id=self._dss_wrapper.participant_id, + ) + + def cleanup(self): + self.begin_cleanup() + + self._delete_isa_if_exists() + + self.end_cleanup() diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_subscription_interactions.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_subscription_interactions.py new file mode 100644 index 0000000000..976d252d04 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_subscription_interactions.py @@ -0,0 +1,241 @@ +from typing import Optional + +import arrow +import loguru + +from monitoring.prober.infrastructure import register_resource_type +from monitoring.uss_qualifier.common_data_definitions import Severity +from monitoring.uss_qualifier.resources.astm.f3411.dss import DSSInstanceResource +from monitoring.uss_qualifier.resources.interuss.id_generator import IDGeneratorResource +from monitoring.uss_qualifier.resources.netrid.service_area import ServiceAreaResource +from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss import utils +from monitoring.uss_qualifier.scenarios.astm.netrid.dss_wrapper import DSSWrapper +from monitoring.uss_qualifier.scenarios.scenario import GenericTestScenario + + +class ISASubscriptionInteractions(GenericTestScenario): + """Based on the test_subscription_isa_interactions.py from the legacy prober tool.""" + + ISA_TYPE = register_resource_type(370, "ISA") + + create_isa_path: str + + write_scope: str + + def __init__( + self, + dss: DSSInstanceResource, + id_generator: IDGeneratorResource, + isa: ServiceAreaResource, + ): + super().__init__() + self._dss = ( + dss.dss_instance + ) # TODO: delete once _delete_isa_if_exists updated to use dss_wrapper + self._dss_wrapper = DSSWrapper(self, dss.dss_instance) + self._isa_id = id_generator.id_factory.make_id( + ISASubscriptionInteractions.ISA_TYPE + ) + # sub id is isa_id with last character replaced with '1' + self._sub_id = self._isa_id[:-1] + "1" + self._isa_version: Optional[str] = None + self._isa = isa.specification + + now = arrow.utcnow().datetime + self._isa_start_time = self._isa.shifted_time_start(now) + self._isa_end_time = self._isa.shifted_time_end(now) + self._isa_area = [vertex.as_s2sphere() for vertex in self._isa.footprint] + + def run(self): + self.begin_test_scenario() + + self._setup_case() + + self.begin_test_case("ISA Subscription Interactions") + self.begin_test_step("ISA Subscription Interactions") + + self._check_subscription_behaviors() + + self.end_test_step() + self.end_test_case() + self.end_test_scenario() + + def _check_subscription_behaviors(self): + """ + - Create an ISA. + - Create a subscription, response should include the pre-existing ISA. + - Modify the ISA, response should include the subscription. + - Delete the ISA, response should include the subscription. + - Delete the subscription. + """ + + # Create an ISA + with self.check("Create an ISA", [self._dss.participant_id]) as check: + created_isa = self._dss_wrapper.put_isa_expect_response_code( + check=check, + expected_error_codes={200}, + area_vertices=self._isa_area, + alt_lo=self._isa.altitude_min, + alt_hi=self._isa.altitude_max, + start_time=self._isa_start_time, + end_time=self._isa_end_time, + uss_base_url=self._isa.base_url, + isa_id=self._isa_id, + isa_version=None, + ) + + # Create a subscription + with self.check( + "Subscription for the ISA's area mentions the ISA", + [self._dss.participant_id], + ) as check: + created_subscription = self._dss_wrapper.put_sub( + check=check, + area_vertices=self._isa_area, + alt_lo=self._isa.altitude_min, + alt_hi=self._isa.altitude_max, + start_time=self._isa_start_time, + end_time=self._isa_end_time, + uss_base_url=self._isa.base_url, + sub_id=self._sub_id, + sub_version=None, + ) + + if created_isa.dss_query.isa.id not in [ + isa.id for isa in created_subscription.isas + ]: + check.record_failed( + summary="Subscription response does not include the freshly created ISA", + severity=Severity.High, + participants=[self._dss.participant_id], + details=f"The subscription created for the area {self._isa_area} is expected to contain the ISA created for this same area. The returned subscription did not mention it.", + query_timestamps=[ + created_isa.dss_query.query.request.timestamp, + created_subscription.query.request.timestamp, + ], + ) + + # Modify the ISA + with self.check( + "Response to the mutation of the ISA contains subscription ID", + [self._dss.participant_id], + ) as check: + mutated_isa = self._dss_wrapper.put_isa_expect_response_code( + check=check, + expected_error_codes={200}, + area_vertices=self._isa_area, + alt_lo=self._isa.altitude_min, + alt_hi=self._isa.altitude_max - 1, # reduce max altitude by one meter + start_time=self._isa_start_time, + end_time=self._isa_end_time, + uss_base_url=self._isa.base_url, + isa_id=self._isa_id, + isa_version=created_isa.dss_query.isa.version, + ) + + subscriptions_to_isa = [] + for returned_subscriber in mutated_isa.dss_query.subscribers: + for sub_in_subscriber in returned_subscriber.raw.subscriptions: + subscriptions_to_isa.append(sub_in_subscriber.subscription_id) + + if created_subscription.subscription.id not in subscriptions_to_isa: + check.record_failed( + summary="ISA mutation response does not contain expected subscription ID", + severity=Severity.High, + participants=[self._dss.participant_id], + details="Mutating an ISA to which a subscription was made, the DSS failed to return the subscription ID in the response.", + query_timestamps=[ + created_isa.dss_query.query.request.timestamp, + created_subscription.query.request.timestamp, + mutated_isa.dss_query.query.request.timestamp, + ], + ) + + # Delete the ISA + with self.check( + "Response to the deletion of the ISA contains subscription ID", + [self._dss.participant_id], + ) as check: + deleted_isa = self._dss_wrapper.del_isa_expect_response_code( + main_check=check, + expected_error_codes={200}, + isa_id=mutated_isa.dss_query.isa.id, + isa_version=mutated_isa.dss_query.isa.version, + ) + + subscriptions_to_deleted_isa = [] + for returned_subscriber in deleted_isa.dss_query.subscribers: + for sub_in_subscriber in returned_subscriber.raw.subscriptions: + subscriptions_to_isa.append(sub_in_subscriber.subscription_id) + + loguru.logger.info( + f"Deleted ISA had subscribers: {subscriptions_to_deleted_isa}" + ) + + if created_subscription.subscription.id not in subscriptions_to_deleted_isa: + check.record_failed( + summary="ISA deletion response does not contain expected subscription ID", + severity=Severity.High, + participants=[self._dss.participant_id], + details="Deleting an ISA to which a subscription was made, the DSS failed to return the subscription ID in the response.", + query_timestamps=[ + created_isa.dss_query.query.request.timestamp, + created_subscription.query.request.timestamp, + deleted_isa.dss_query.query.request.timestamp, + ], + ) + + # Delete the subscription + with self.check( + "Successful subscription deletion", + [self._dss.participant_id], + ) as check: + self._dss_wrapper.del_sub( + check=check, + sub_id=self._sub_id, + sub_version=created_subscription.subscription.version, + ) + + def _setup_case(self): + self.begin_test_case("Setup") + + def _ensure_clean_workspace_step(): + self.begin_test_step("Ensure clean workspace") + + self._delete_isa_if_exists() + + self.end_test_step() + + _ensure_clean_workspace_step() + + self.end_test_case() + + def _delete_isa_if_exists(self): + utils.delete_isa_if_exists( + self, + isa_id=self._isa_id, + rid_version=self._dss.rid_version, + session=self._dss.client, + server_id=self._dss_wrapper.participant_id, + ) + + def _clean_any_sub(self): + with self.check( + "Successful subscription query", [self._dss.participant_id] + ) as check: + fetched = self._dss_wrapper.search_subs( + check, [vertex.as_s2sphere() for vertex in self._isa.footprint] + ) + for sub_id in fetched.subscriptions.keys(): + with self.check( + "Successful subscription deletion", [self._dss.participant_id] + ) as check: + self._dss_wrapper.cleanup_sub(check, sub_id=sub_id) + + def cleanup(self): + self.begin_cleanup() + + self._delete_isa_if_exists() + self._clean_any_sub() + + self.end_cleanup() diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_simple.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_simple.py new file mode 100644 index 0000000000..10e4f6bca3 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_simple.py @@ -0,0 +1,102 @@ +from datetime import timedelta + +import arrow +import datetime + +from monitoring.monitorlib import schema_validation +from monitoring.monitorlib.fetch import rid as fetch +from monitoring.monitorlib.mutate import rid as mutate +from monitoring.monitorlib.rid import RIDVersion +from monitoring.prober.infrastructure import register_resource_type +from monitoring.uss_qualifier.common_data_definitions import Severity +from monitoring.uss_qualifier.resources.astm.f3411.dss import DSSInstanceResource +from monitoring.uss_qualifier.resources.interuss.id_generator import IDGeneratorResource +from monitoring.uss_qualifier.resources.netrid.service_area import ServiceAreaResource +from monitoring.uss_qualifier.scenarios.astm.netrid.dss_wrapper import DSSWrapper +from monitoring.uss_qualifier.scenarios.scenario import ( + GenericTestScenario, + PendingCheck, +) +from monitoring.monitorlib.mutate.rid import ChangedSubscription + +from typing import Dict + + +class SubscriptionSimple(GenericTestScenario): + """Based on prober/rid/v2/test_subscription_validation.py from the legacy prober tool.""" + + SUB_TYPE = register_resource_type(371, "Subscription") + + def __init__( + self, + dss: DSSInstanceResource, + id_generator: IDGeneratorResource, + isa: ServiceAreaResource, + ): + """ + + Args: + dss: dss to test + id_generator: will let us generate specific identifiers + isa: Service Area to use for the tests. It should be an area for which the DSS is responsible, + but has no other requirements. + """ + super().__init__() + # This is an UTMClientSession + self._dss = dss.dss_instance + self._dss_wrapper = DSSWrapper(self, self._dss) + # TODO: the id_factory seems to generate static IDs: + # for creating different subscriptions this probably won't do. + self._sub_id = id_generator.id_factory.make_id(self.SUB_TYPE) + self._isa = isa.specification + + def run(self): + self.begin_test_scenario() + + self._setup_case() + + self.begin_test_case("Subscription Simple") + self.begin_test_step("Subscription Simple") + + self.end_test_step() + self.end_test_case() + + self.end_test_scenario() + + def _setup_case(self): + self.begin_test_case("Setup") + + self._ensure_clean_workspace_step() + + self.end_test_case() + + def _clean_any_sub(self): + with self.check( + "Successful subscription query", [self._dss.participant_id] + ) as check: + fetched = self._dss_wrapper.search_subs( + check, [vertex.as_s2sphere() for vertex in self._isa.footprint] + ) + for sub_id in fetched.subscriptions.keys(): + with self.check( + "Successful subscription deletion", [self._dss.participant_id] + ) as check: + self._dss_wrapper.cleanup_sub(check, sub_id=sub_id) + + def _ensure_clean_workspace_step(self): + self.begin_test_step("Ensure clean workspace") + + self._clean_any_sub() + + self.end_test_step() + + def _simple_subscription_validation(self): + # TODO + pass + + def cleanup(self): + self.begin_cleanup() + + self._clean_any_sub() + + self.end_cleanup() diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/__init__.py b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/__init__.py index 3a58386869..b77388ac4d 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/__init__.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/__init__.py @@ -1,4 +1,7 @@ from .isa_simple import ISASimple from .isa_validation import ISAValidation +from .isa_expiry import ISAExpiry +from .isa_subscription_interactions import ISASubscriptionInteractions +from .subscription_simple import SubscriptionSimple from .subscription_validation import SubscriptionValidation from .crdb_access import CRDBAccess diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_expiry.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_expiry.md new file mode 100644 index 0000000000..b5f377caca --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_expiry.md @@ -0,0 +1,70 @@ +# ASTM NetRID DSS: ISA Expiry test scenario + +## Overview + +Perform basic operations on a single DSS instance in order to verify that it handles ISA expiry correctly. + +## Resources + +### dss + +[`DSSInstanceResource`](../../../../../resources/astm/f3411/dss.py) to be tested in this scenario. + +### id_generator + +[`IDGeneratorResource`](../../../../../resources/interuss/id_generator.py) providing the ISA ID for this scenario. + +### isa + +[`ServiceAreaResource`](../../../../../resources/netrid/service_area.py) describing an ISA to be created. + +## Setup test case + +### Ensure clean workspace test step + +This scenario creates an ISA with a known ID. This step ensures that ISA does not exist before the start of the main +part of the test. + +#### Successful ISA query check + +**[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** requires the implementation of the DSS endpoint enabling retrieval of information about a specific ISA; if the individual ISA cannot be retrieved and the error isn't a 404, then this requirement isn't met. + +#### Removed pre-existing ISA check + +If an ISA with the intended ID is already present in the DSS, it needs to be removed before proceeding with the test. If that ISA cannot be deleted, then the **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** requirement to implement the ISA deletion endpoint might not be met. + +#### Notified subscriber check + +When a pre-existing ISA needs to be deleted to ensure a clean workspace, any subscribers to ISAs in that area must be notified (as specified by the DSS). If a notification cannot be delivered, then the **[astm.f3411.v19.NET0710](../../../../../requirements/astm/f3411/v19.md)** requirement to implement the POST ISAs endpoint isn't met. + +## ISA Expiry test case + +### ISA Expiry test step + +#### Create short lived ISA check + +Not allowing an ISA to be created violates **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** + +#### Expired ISAs are not part of search results check + +If an ISA is expired, it should not be returned in search results. If it is the **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** requirement isn't met. + +#### An expired ISA can be queried by its ID check + +Not returning an ISA that is currently expired when it is queried by ID is a violation of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)**. + +## Cleanup + +The cleanup phase of this test scenario attempts to remove the ISA if the test ended prematurely. + +### Successful ISA query check + +**[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** requires the implementation of the DSS endpoint enabling retrieval of information about a specific ISA; if the individual ISA cannot be retrieved and the error isn't a 404, then this requirement isn't met. + +### Removed pre-existing ISA check + +If an ISA with the intended ID is still present in the DSS, it needs to be removed before exiting the test. If that ISA cannot be deleted, then the **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** requirement to implement the ISA deletion endpoint might not be met. + +### Notified subscriber check + +When an ISA is deleted, subscribers must be notified. If a subscriber cannot be notified, that subscriber USS did not correctly implement "POST Identification Service Area" in **[astm.f3411.v19.NET0730](../../../../../requirements/astm/f3411/v19.md)**. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_expiry.py b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_expiry.py new file mode 100644 index 0000000000..616a8ad421 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_expiry.py @@ -0,0 +1,8 @@ +from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss.isa_expiry import ( + ISAExpiry as CommonISAExpiry, +) +from monitoring.uss_qualifier.scenarios.scenario import TestScenario + + +class ISAExpiry(TestScenario, CommonISAExpiry): + pass diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_subscription_interactions.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_subscription_interactions.md new file mode 100644 index 0000000000..334dddb43e --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_subscription_interactions.md @@ -0,0 +1,93 @@ +# ASTM NetRID DSS: ISA Subscription Interactions test scenario + +## Overview + +Verifies that interactions between ISAs and subscriptions happen as expected. + +## Resources + +### dss + +[`DSSInstanceResource`](../../../../../resources/astm/f3411/dss.py) to be tested in this scenario. + +### id_generator + +[`IDGeneratorResource`](../../../../../resources/interuss/id_generator.py) providing the ISA ID for this scenario. + +### isa + +[`ServiceAreaResource`](../../../../../resources/netrid/service_area.py) describing an ISA to be created. + +## Setup test case + +### Ensure clean workspace test step + +This scenario creates an ISA with a known ID. This step ensures that ISA does not exist before the start of the main +part of the test. + +#### Successful ISA query check + +**[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** requires the implementation of the DSS endpoint enabling retrieval of information about a specific ISA; if the individual ISA cannot be retrieved and the error isn't a 404, then this requirement isn't met. + +#### Removed pre-existing ISA check + +If an ISA with the intended ID is already present in the DSS, it needs to be removed before proceeding with the test. If that ISA cannot be deleted, then the **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** requirement to implement the ISA deletion endpoint might not be met. + +#### Notified subscriber check + +When a pre-existing ISA needs to be deleted to ensure a clean workspace, any subscribers to ISAs in that area must be notified (as specified by the DSS). If a notification cannot be delivered, then the **[astm.f3411.v19.NET0710](../../../../../requirements/astm/f3411/v19.md)** requirement to implement the POST ISAs endpoint isn't met. + +#### Successful subscription query check + +If the query for subscriptions fails, the "GET Subscriptions" portion of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** was not met. + +#### Successful subscription deletion + +If the deletion attempt fails, the "DELETE Subscription" portion of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** was not met. + +## ISA Subscription Interactions test case + +### ISA Subscription Interactions test step + +#### Create an ISA check + +The DSS should let is create an ISA, according to **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** + +#### Subscription for the ISA's area mentions the ISA check + +A subscription that is created for a volume that intersects with the previously created ISA should mention +the previously created ISA. If not, the serving DSS is in violation of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)**. + +#### Response to the mutation of the ISA contains subscription ID check + +When an ISA is mutated, the DSS must return the identifiers for any subscription that was made to the ISA, +or be in violation of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)**. + +#### Response to the deletion of the ISA contains subscription ID check + +When an ISA is deleted, the DSS must return the identifiers for any subscription that was made to the ISA, +or be in violation of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)**. + +## Cleanup + +The cleanup phase of this test scenario attempts to remove the ISA if the test ended prematurely. + +### Successful ISA query check + +**[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** requires the implementation of the DSS endpoint enabling retrieval of information about a specific ISA; if the individual ISA cannot be retrieved and the error isn't a 404, then this requirement isn't met. + +### Removed pre-existing ISA check + +If an ISA with the intended ID is still present in the DSS, it needs to be removed before exiting the test. If that ISA cannot be deleted, then the **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** requirement to implement the ISA deletion endpoint might not be met. + +### Notified subscriber check + +When an ISA is deleted, subscribers must be notified. If a subscriber cannot be notified, that subscriber USS did not correctly implement "POST Identification Service Area" in **[astm.f3411.v19.NET0730](../../../../../requirements/astm/f3411/v19.md)**. + +### Successful subscription query check + +If a subscription with the intended ID is still present in the DSS, it needs to be removed before exiting the test. If that subscription cannot be listed, then the **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** requirement is not met. + +### Successful subscription deletion check + +If the deletion attempt fails, the "DELETE Subscription" portion of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** was not met. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_subscription_interactions.py b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_subscription_interactions.py new file mode 100644 index 0000000000..b6acd67db8 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_subscription_interactions.py @@ -0,0 +1,8 @@ +from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss.isa_subscription_interactions import ( + ISASubscriptionInteractions as CommonISASubscriptionInteractions, +) +from monitoring.uss_qualifier.scenarios.scenario import TestScenario + + +class ISASubscriptionInteractions(TestScenario, CommonISASubscriptionInteractions): + pass diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_simple.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_simple.md new file mode 100644 index 0000000000..6373160e34 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_simple.md @@ -0,0 +1,51 @@ +# ASTM NetRID DSS: Subscription Simple test scenario + +## Overview + +Perform basic operations on a single DSS instance to create, update and delete subscriptions + +## Resources + +### dss + +[`DSSInstanceResource`](../../../../../resources/astm/f3411/dss.py) to be tested in this scenario. + +### id_generator + +[`IDGeneratorResource`](../../../../../resources/interuss/id_generator.py) providing the Subscription IDs for this scenario. + +### isa + +[`ServiceAreaResource`](../../../../../resources/netrid/service_area.py) describing a service area for which to subscribe. + +## Setup test case + +### Ensure clean workspace test step + +This step ensures that we remove any subscription that may already exist for the service area. First, the DSS is queried for any applicable existing subscriptions, and then any subscriptions found are deleted. + +#### Successful subscription query check + +If the query for subscriptions fails, the "GET Subscriptions" portion of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** was not met. + +#### Successful subscription deletion check + +If the deletion attempt fails, the "DELETE Subscription" portion of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** was not met. + +## Subscription Simple test case + +### Subscription Simple test step + +TODO + +## Cleanup + +The cleanup phase of this test scenario will remove any subscription that may have been created during the test and that intersects with the test ISA. + +### Successful subscription query check + +If the query for subscriptions fails, the "GET Subscriptions" portion of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** was not met. + +### Successful subscription deletion + +If the deletion attempt fails, the "DELETE Subscription" portion of **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** was not met. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_simple.py b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_simple.py new file mode 100644 index 0000000000..25f95e1d88 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_simple.py @@ -0,0 +1,8 @@ +from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss.subscription_simple import ( + SubscriptionSimple as CommonSubscriptionSimple, +) +from monitoring.uss_qualifier.scenarios.scenario import TestScenario + + +class SubscriptionSimple(TestScenario, CommonSubscriptionSimple): + pass diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_validation.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_validation.md index 7b987cc193..6f78f8bfd9 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_validation.md +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_validation.md @@ -28,7 +28,7 @@ This step ensures that we remove any subscription that may already exist for the If the query for subscriptions fails, **[astm.f3411.v19.DSS0030,f](../../../../../requirements/astm/f3411/v19.md)** was not met. -#### Successful subscription deletion +#### Successful subscription deletion check If the deletion attempt fails, **[astm.f3411.v19.DSS0030,d](../../../../../requirements/astm/f3411/v19.md)** was not met. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/__init__.py b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/__init__.py index 3a58386869..77eade4f6e 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/__init__.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/__init__.py @@ -1,4 +1,6 @@ from .isa_simple import ISASimple from .isa_validation import ISAValidation +from .isa_expiry import ISAExpiry +from .isa_subscription_interactions import ISASubscriptionInteractions from .subscription_validation import SubscriptionValidation from .crdb_access import CRDBAccess diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_expiry.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_expiry.md new file mode 100644 index 0000000000..9d9f833553 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_expiry.md @@ -0,0 +1,70 @@ +# ASTM NetRID DSS: ISA Expiry test scenario + +## Overview + +Perform basic operations on a single DSS instance in order to verify that it handles ISA expiry correctly. + +## Resources + +### dss + +[`DSSInstanceResource`](../../../../../resources/astm/f3411/dss.py) to be tested in this scenario. + +### id_generator + +[`IDGeneratorResource`](../../../../../resources/interuss/id_generator.py) providing the ISA ID for this scenario. + +### isa + +[`ServiceAreaResource`](../../../../../resources/netrid/service_area.py) describing an ISA to be created. + +## Setup test case + +### Ensure clean workspace test step + +This scenario creates an ISA with a known ID. This step ensures that ISA does not exist before the start of the main +part of the test. + +#### Successful ISA query check + +**[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** requires the implementation of the DSS endpoint enabling retrieval of information about a specific ISA; if the individual ISA cannot be retrieved and the error isn't a 404, then this requirement isn't met. + +#### Removed pre-existing ISA check + +If an ISA with the intended ID is already present in the DSS, it needs to be removed before proceeding with the test. If that ISA cannot be deleted, then the **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** requirement to implement the ISA deletion endpoint might not be met. + +#### Notified subscriber check + +When a pre-existing ISA needs to be deleted to ensure a clean workspace, any subscribers to ISAs in that area must be notified (as specified by the DSS). If a notification cannot be delivered, then the **[astm.f3411.v22a.NET0710](../../../../../requirements/astm/f3411/v22a.md)** requirement to implement the POST ISAs endpoint isn't met. + +## ISA Expiry test case + +### ISA Expiry test step + +#### Create short lived ISA check + +Not allowing an ISA to be created violates **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** + +#### Expired ISAs are not part of search results check + +If an ISA is expired, it should not be returned in search results. If it is the **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** requirement isn't met. + +#### An expired ISA can be queried by its ID check + +Not returning an ISA that is currently expired when it is queried by ID is a violation of **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)**. + +## Cleanup + +The cleanup phase of this test scenario attempts to remove the ISA if the test ended prematurely. + +### Successful ISA query check + +**[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** requires the implementation of the DSS endpoint enabling retrieval of information about a specific ISA; if the individual ISA cannot be retrieved and the error isn't a 404, then this requirement isn't met. + +### Removed pre-existing ISA check + +If an ISA with the intended ID is still present in the DSS, it needs to be removed before exiting the test. If that ISA cannot be deleted, then the **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** requirement to implement the ISA deletion endpoint might not be met. + +### Notified subscriber check + +When an ISA is deleted, subscribers must be notified. If a subscriber cannot be notified, that subscriber USS did not correctly implement "POST Identification Service Area" in **[astm.f3411.v22a.NET0730](../../../../../requirements/astm/f3411/v22a.md)**. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_expiry.py b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_expiry.py new file mode 100644 index 0000000000..616a8ad421 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_expiry.py @@ -0,0 +1,8 @@ +from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss.isa_expiry import ( + ISAExpiry as CommonISAExpiry, +) +from monitoring.uss_qualifier.scenarios.scenario import TestScenario + + +class ISAExpiry(TestScenario, CommonISAExpiry): + pass diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.md new file mode 100644 index 0000000000..4140985d05 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.md @@ -0,0 +1,93 @@ +# ASTM NetRID DSS: ISA Subscription Interactions test scenario + +## Overview + +Verifies that interactions between ISAs and subscriptions happen as expected. + +## Resources + +### dss + +[`DSSInstanceResource`](../../../../../resources/astm/f3411/dss.py) to be tested in this scenario. + +### id_generator + +[`IDGeneratorResource`](../../../../../resources/interuss/id_generator.py) providing the ISA ID for this scenario. + +### isa + +[`ServiceAreaResource`](../../../../../resources/netrid/service_area.py) describing an ISA to be created. + +## Setup test case + +### Ensure clean workspace test step + +This scenario creates an ISA with a known ID. This step ensures that ISA does not exist before the start of the main +part of the test. + +#### Successful ISA query check + +**[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** requires the implementation of the DSS endpoint enabling retrieval of information about a specific ISA; if the individual ISA cannot be retrieved and the error isn't a 404, then this requirement isn't met. + +#### Removed pre-existing ISA check + +If an ISA with the intended ID is already present in the DSS, it needs to be removed before proceeding with the test. If that ISA cannot be deleted, then the **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** requirement to implement the ISA deletion endpoint might not be met. + +#### Notified subscriber check + +When a pre-existing ISA needs to be deleted to ensure a clean workspace, any subscribers to ISAs in that area must be notified (as specified by the DSS). If a notification cannot be delivered, then the **[astm.f3411.v22a.NET0710](../../../../../requirements/astm/f3411/v22a.md)** requirement to implement the POST ISAs endpoint isn't met. + +#### Successful subscription query check + +If the query for subscriptions fails, the "GET Subscriptions" portion of **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** was not met. + +#### Successful subscription deletion + +If the deletion attempt fails, the "DELETE Subscription" portion of **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** was not met. + +## ISA Subscription Interactions test case + +### ISA Subscription Interactions test step + +#### Create an ISA check + +The DSS should let is create an ISA, according to **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** + +#### Subscription for the ISA's area mentions the ISA check + +A subscription that is created for a volume that intersects with the previously created ISA should mention +the previously created ISA. If not, the serving DSS is in violation of **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)**. + +#### Response to the mutation of the ISA contains subscription ID check + +When an ISA is mutated, the DSS must return the identifiers for any subscription that was made to the ISA, +or be in violation of **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)**. + +#### Response to the deletion of the ISA contains subscription ID check + +When an ISA is deleted, the DSS must return the identifiers for any subscription that was made to the ISA, +or be in violation of **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)**. + +## Cleanup + +The cleanup phase of this test scenario attempts to remove the ISA if the test ended prematurely. + +### Successful ISA query check + +**[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** requires the implementation of the DSS endpoint enabling retrieval of information about a specific ISA; if the individual ISA cannot be retrieved and the error isn't a 404, then this requirement isn't met. + +### Removed pre-existing ISA check + +If an ISA with the intended ID is still present in the DSS, it needs to be removed before exiting the test. If that ISA cannot be deleted, then the **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** requirement to implement the ISA deletion endpoint might not be met. + +### Notified subscriber check + +When an ISA is deleted, subscribers must be notified. If a subscriber cannot be notified, that subscriber USS did not correctly implement "POST Identification Service Area" in **[astm.f3411.v22a.NET0730](../../../../../requirements/astm/f3411/v22a.md)**. + +### Successful subscription query check + +If a subscription with the intended ID is still present in the DSS, it needs to be removed before exiting the test. If that subscription cannot be listed, then the **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** requirement is not met. + +### Successful subscription deletion check + +If the deletion attempt fails, the "DELETE Subscription" portion of **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** was not met. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.py b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.py new file mode 100644 index 0000000000..b6acd67db8 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.py @@ -0,0 +1,8 @@ +from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss.isa_subscription_interactions import ( + ISASubscriptionInteractions as CommonISASubscriptionInteractions, +) +from monitoring.uss_qualifier.scenarios.scenario import TestScenario + + +class ISASubscriptionInteractions(TestScenario, CommonISASubscriptionInteractions): + pass diff --git a/monitoring/uss_qualifier/suites/astm/netrid/f3411_19.md b/monitoring/uss_qualifier/suites/astm/netrid/f3411_19.md index 347a1f1add..5dc4337af0 100644 --- a/monitoring/uss_qualifier/suites/astm/netrid/f3411_19.md +++ b/monitoring/uss_qualifier/suites/astm/netrid/f3411_19.md @@ -21,7 +21,12 @@