From 58feeac7a75388b0cea1941a7e9bedf0fe1c461e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Misbach?= Date: Fri, 22 Sep 2023 02:48:21 +0200 Subject: [PATCH] [uss_qualifier/netrid/dss/isa_simple] Refactor and complete create case (#204) * [uss_qualifier/netrid/dss/isa_simple] Refactor and complete create case * add v19 ISASimple * [uss_qualifier/scenarios/documentation] Allow additional checks when a step is linked * move back checks as part of DSSWrapper * fixes following review * update submodules and uas_standards * [uss_qualifier/scenarios/aggregate_checks] Convert unattributed queries check to a note * DSS interop: put back record fail in check * cleanups --- .../mock_uss/riddp/routes_observation.py | 4 +- monitoring/mock_uss/tracer/tracer_poll.py | 4 +- monitoring/monitorlib/fetch/rid.py | 16 +- monitoring/monitorlib/geo.py | 8 + monitoring/monitorlib/mutate/rid.py | 13 +- monitoring/monitorlib/rid.py | 4 +- .../configurations/dev/library/resources.yaml | 15 +- .../resources/netrid/service_area.py | 30 ++- .../astm/netrid/common/dss/isa_simple.py | 184 ++++++------------ .../common/dss/subscription_validation.py | 4 +- .../netrid/common/dss_interoperability.py | 4 +- .../scenarios/astm/netrid/dss_wrapper.py | 178 ++++++++++++----- .../scenarios/astm/netrid/v19/dss/__init__.py | 1 + .../astm/netrid/v19/dss/isa_simple.md | 84 ++++++++ .../astm/netrid/v19/dss/isa_simple.py | 8 + .../astm/netrid/v19/dss/test_steps/put_isa.md | 36 ++++ .../astm/netrid/v19/dss_interoperability.md | 8 +- .../astm/netrid/v22a/dss/isa_simple.md | 31 ++- .../netrid/v22a/dss/test_steps/put_isa.md | 36 ++++ .../astm/netrid/v22a/dss_interoperability.md | 8 +- .../suites/astm/netrid/f3411_19.md | 11 +- .../astm/netrid/f3411_19/dss_probing.md | 17 +- .../astm/netrid/f3411_19/dss_probing.yaml | 6 + .../suites/astm/netrid/f3411_22a.md | 2 +- .../suites/uspace/network_identification.md | 2 +- .../suites/uspace/required_services.md | 2 +- 26 files changed, 480 insertions(+), 236 deletions(-) create mode 100644 monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_simple.md create mode 100644 monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_simple.py create mode 100644 monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/test_steps/put_isa.md create mode 100644 monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/test_steps/put_isa.md diff --git a/monitoring/mock_uss/riddp/routes_observation.py b/monitoring/mock_uss/riddp/routes_observation.py index ec2ef5a840..540977dbc3 100644 --- a/monitoring/mock_uss/riddp/routes_observation.py +++ b/monitoring/mock_uss/riddp/routes_observation.py @@ -110,7 +110,9 @@ def riddp_display_data() -> Tuple[str, int]: # Get ISAs in the DSS t = arrow.utcnow().datetime - isa_list: FetchedISAs = fetch.isas(view, t, t, rid_version, utm_client) + isa_list: FetchedISAs = fetch.isas( + geo.get_latlngrect_vertices(view), t, t, rid_version, utm_client + ) if not isa_list.success: msg = f"Error fetching ISAs from DSS: {isa_list.errors}" logger.error(msg) diff --git a/monitoring/mock_uss/tracer/tracer_poll.py b/monitoring/mock_uss/tracer/tracer_poll.py index 0d9eb7e5eb..4e29c6a8d0 100755 --- a/monitoring/mock_uss/tracer/tracer_poll.py +++ b/monitoring/mock_uss/tracer/tracer_poll.py @@ -21,7 +21,7 @@ from monitoring.mock_uss.tracer import context from monitoring.monitorlib.fetch.rid import FetchedISAs from monitoring.monitorlib.fetch.scd import FetchedEntities -from monitoring.monitorlib.geo import make_latlng_rect +from monitoring.monitorlib.geo import make_latlng_rect, get_latlngrect_vertices from monitoring.monitorlib.infrastructure import UTMClientSession from monitoring.monitorlib.multiprocessing import SynchronizedValue @@ -97,7 +97,7 @@ def poll_observation_areas() -> None: def poll_isas(area: ObservationArea, logger: tracerlog.Logger) -> None: rid_client = context.get_client(area.f3411.auth_spec, area.f3411.dss_base_url) - box = make_latlng_rect(area.area.volume) + box = get_latlngrect_vertices(make_latlng_rect(area.area.volume)) log_name = "poll_isas" t0 = datetime.datetime.utcnow() diff --git a/monitoring/monitorlib/fetch/rid.py b/monitoring/monitorlib/fetch/rid.py index 3f52335bfc..be048f2965 100644 --- a/monitoring/monitorlib/fetch/rid.py +++ b/monitoring/monitorlib/fetch/rid.py @@ -850,7 +850,7 @@ def has_different_content_than(self, other: Any) -> bool: def isas( - box: s2sphere.LatLngRect, + area: List[s2sphere.LatLng], start_time: datetime.datetime, end_time: datetime.datetime, rid_version: RIDVersion, @@ -862,7 +862,7 @@ def isas( t1 = rid_version.format_time(end_time) if rid_version == RIDVersion.f3411_19: op = v19.api.OPERATIONS[v19.api.OperationID.SearchIdentificationServiceAreas] - area = rid_v1.geo_polygon_string_from_s2(geo.get_latlngrect_vertices(box)) + area = rid_v1.geo_polygon_string_from_s2(area) url = f"{dss_base_url}{op.path}?area={area}&earliest_time={t0}&latest_time={t1}" return FetchedISAs( v19_query=fetch.query_and_describe( @@ -875,7 +875,7 @@ def isas( ) elif rid_version == RIDVersion.f3411_22a: op = v22a.api.OPERATIONS[v22a.api.OperationID.SearchIdentificationServiceAreas] - area = rid_v2.geo_polygon_string_from_s2(geo.get_latlngrect_vertices(box)) + area = rid_v2.geo_polygon_string_from_s2(area) url = f"{dss_base_url}{op.path}?area={area}&earliest_time={t0}&latest_time={t1}" return FetchedISAs( v22a_query=fetch.query_and_describe( @@ -1162,7 +1162,15 @@ def all_flights( server_id: Optional[str] = None, ) -> FetchedFlights: t = datetime.datetime.utcnow() - isa_list = isas(area, t, t, rid_version, session, dss_base_url, server_id=server_id) + isa_list = isas( + geo.get_latlngrect_vertices(area), + t, + t, + rid_version, + session, + dss_base_url, + server_id=server_id, + ) uss_flight_queries: Dict[str, FetchedUSSFlights] = {} uss_flight_details_queries: Dict[str, FetchedUSSFlightDetails] = {} diff --git a/monitoring/monitorlib/geo.py b/monitoring/monitorlib/geo.py index e58c18fa74..9aefb6a04f 100644 --- a/monitoring/monitorlib/geo.py +++ b/monitoring/monitorlib/geo.py @@ -19,8 +19,16 @@ class DistanceUnits(str, Enum): class LatLngPoint(ImplicitDict): + """Vertex in latitude and longitude""" + lat: float + """Latitude (degrees)""" + lng: float + """Longitude (degrees)""" + + def as_s2sphere(self) -> s2sphere.LatLng: + return s2sphere.LatLng.from_degrees(self.lat, self.lng) class Radius(ImplicitDict): diff --git a/monitoring/monitorlib/mutate/rid.py b/monitoring/monitorlib/mutate/rid.py index 12aa8453d7..dd42e2cfc4 100644 --- a/monitoring/monitorlib/mutate/rid.py +++ b/monitoring/monitorlib/mutate/rid.py @@ -14,7 +14,12 @@ import yaml from yaml.representer import Representer -from monitoring.monitorlib import fetch, infrastructure, rid_v1, rid_v2 +from monitoring.monitorlib import ( + fetch, + infrastructure, + rid_v1, + rid_v2, +) class ChangedSubscription(RIDQuery): @@ -327,7 +332,11 @@ def _v22a_response( @property def errors(self) -> List[str]: - if self.status_code != 200: + # Tolerate reasonable-but-technically-incorrect code 201 + if not ( + self.status_code == 200 + or (self.mutation == "create" and self.status_code == 201) + ): return ["Failed to mutate ISA ({})".format(self.status_code)] if self.query.response.json is None: return ["ISA response did not include valid JSON"] diff --git a/monitoring/monitorlib/rid.py b/monitoring/monitorlib/rid.py index 196409a752..ce1509035d 100644 --- a/monitoring/monitorlib/rid.py +++ b/monitoring/monitorlib/rid.py @@ -5,6 +5,7 @@ from monitoring.monitorlib import schema_validation from uas_standards.astm.f3411 import v19, v22a +import uas_standards.astm.f3411.v19.api import uas_standards.astm.f3411.v19.constants import uas_standards.astm.f3411.v22a.api import uas_standards.astm.f3411.v22a.constants @@ -202,7 +203,8 @@ def dss_max_subscriptions_per_area(self) -> int: def flights_url_of(self, base_url: str) -> str: if self == RIDVersion.f3411_19: - return base_url + flights_path = v19.api.OPERATIONS[v19.api.OperationID.SearchFlights].path + return base_url + flights_path elif self == RIDVersion.f3411_22a: flights_path = v22a.api.OPERATIONS[v22a.api.OperationID.SearchFlights].path return base_url + flights_path diff --git a/monitoring/uss_qualifier/configurations/dev/library/resources.yaml b/monitoring/uss_qualifier/configurations/dev/library/resources.yaml index e299b45688..324a0b5d61 100644 --- a/monitoring/uss_qualifier/configurations/dev/library/resources.yaml +++ b/monitoring/uss_qualifier/configurations/dev/library/resources.yaml @@ -32,12 +32,19 @@ net_rid: specification: base_url: https://uss_qualifier.test.utm/dummy_base_url footprint: - lat_min: 37.1853 - lng_min: -80.6140 - lat_max: 37.2148 - lng_max: -80.5440 + - lat: 37.1853 + lng: -80.6140 + - lat: 37.2148 + lng: -80.6140 + - lat: 37.2148 + lng: -80.5440 + - lat: 37.1853 + lng: -80.5440 altitude_min: 0 altitude_max: 3048 + reference_time: '2023-01-10T00:00:00.123456+00:00' + time_start: '2023-01-10T00:00:01.123456+00:00' + time_end: '2023-01-10T01:00:01.123456+00:00' net_rid_sims: adjacent_circular_flights_data: diff --git a/monitoring/uss_qualifier/resources/netrid/service_area.py b/monitoring/uss_qualifier/resources/netrid/service_area.py index d14ce141dc..826007354e 100644 --- a/monitoring/uss_qualifier/resources/netrid/service_area.py +++ b/monitoring/uss_qualifier/resources/netrid/service_area.py @@ -1,5 +1,8 @@ -from implicitdict import ImplicitDict -from monitoring.monitorlib.geo import LatLngBoundingBox +import datetime +from typing import List + +from implicitdict import ImplicitDict, StringBasedDateTime +from monitoring.monitorlib.geo import LatLngPoint from monitoring.uss_qualifier.resources.resource import Resource @@ -12,7 +15,7 @@ class ServiceAreaSpecification(ImplicitDict): This URL will probably not identify a real resource in tests.""" - footprint: LatLngBoundingBox + footprint: List[LatLngPoint] """2D outline of service area""" altitude_min: float = 0 @@ -21,6 +24,27 @@ class ServiceAreaSpecification(ImplicitDict): altitude_max: float = 3048 """Upper altitude bound of service area, meters above WGS84 ellipsoid""" + reference_time: StringBasedDateTime + """Reference time used to adjust start and end times at runtime""" + + time_start: StringBasedDateTime + """Start time of service area (relative to reference_time)""" + + time_end: StringBasedDateTime + """End time of service area (relative to reference_time)""" + + def shifted_time_start( + self, new_reference_time: datetime.datetime + ) -> datetime.datetime: + dt = new_reference_time - self.reference_time.datetime + return self.time_start.datetime + dt + + def shifted_time_end( + self, new_reference_time: datetime.datetime + ) -> datetime.datetime: + dt = new_reference_time - self.reference_time.datetime + return self.time_end.datetime + dt + class ServiceAreaResource(Resource[ServiceAreaSpecification]): specification: ServiceAreaSpecification diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_simple.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_simple.py index 5a9fbf28cb..06aff7fe90 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_simple.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_simple.py @@ -1,8 +1,7 @@ -from datetime import timedelta +from typing import Optional import arrow -from monitoring.monitorlib import schema_validation from monitoring.monitorlib.fetch import rid as fetch from monitoring.monitorlib.mutate import rid as mutate from monitoring.prober.infrastructure import register_resource_type @@ -10,12 +9,10 @@ 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 -MAX_SKEW = 1e-6 # seconds maximum difference between expected and actual timestamps - - class ISASimple(GenericTestScenario): """Based on prober/rid/v2/test_isa_simple.py from the legacy prober tool.""" @@ -28,10 +25,19 @@ def __init__( isa: ServiceAreaResource, ): super().__init__() - self._dss = dss.dss_instance + 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(ISASimple.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() @@ -45,7 +51,14 @@ def run(self): def _setup_case(self): self.begin_test_case("Setup") - self._ensure_clean_workspace_step() + 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() @@ -98,136 +111,57 @@ def _delete_isa_if_exists(self): query_timestamps=[notification.query.request.timestamp], ) - def _ensure_clean_workspace_step(self): - self.begin_test_step("Ensure clean workspace") + def _get_isa_by_id_step(self): + self.begin_test_step("Get ISA by ID") - self._delete_isa_if_exists() + with self.check( + "Successful ISA query", [self._dss_wrapper.participant_id] + ) as check: + fetched = self._dss_wrapper.get_isa(check, self._isa_id) + + with self.check( + "ISA version match", [self._dss_wrapper.participant_id] + ) as check: + if ( + self._isa_version is not None + and fetched.isa.version != self._isa_version + ): + check.record_failed( + "DSS returned ISA with incorrect version", + Severity.High, + f"DSS should have returned an ISA with the version {self._isa_version}, but instead the ISA returned had the version {fetched.isa.version}", + query_timestamps=[fetched.query.request.timestamp], + ) self.end_test_step() def _create_and_check_isa_case(self): self.begin_test_case("Create and check ISA") - self._create_isa_step() - - # TODO: Get ISA by ID - - self.end_test_case() - - def _create_isa_step(self): - self.begin_test_step("Create ISA") - - start_time = arrow.utcnow().datetime + timedelta(seconds=1) - end_time = start_time + timedelta(minutes=60) - area = self._isa.footprint.to_vertices() - isa_change = mutate.put_isa( - area_vertices=area, - start_time=start_time, - end_time=end_time, - uss_base_url=self._isa.base_url, - isa_id=self._isa_id, - rid_version=self._dss.rid_version, - utm_client=self._dss.client, - isa_version=None, - alt_lo=self._isa.altitude_min, - alt_hi=self._isa.altitude_max, - server_id=self._dss.participant_id, - ) - self.record_query(isa_change.dss_query.query) - for notification_query in isa_change.notifications.values(): - self.record_query(notification_query.query) - t_dss = isa_change.dss_query.query.request.timestamp - - with self.check("ISA created", [self._dss.participant_id]) as check: - if isa_change.dss_query.status_code == 200: - check.record_passed() - elif isa_change.dss_query.status_code == 201: - check.record_failed( - f"PUT ISA returned technically-incorrect 201", - Severity.Low, - "DSS should return 200 from PUT ISA, but instead returned the reasonable-but-technically-incorrect code 201", - query_timestamps=[t_dss], - ) - else: - check.record_failed( - f"PUT ISA returned {isa_change.dss_query.status_code}", - Severity.High, - f"DSS should return 200 from PUT ISA, but instead returned {isa_change.dss_query.status_code}", - query_timestamps=[t_dss], + def _create_isa_step(): + self.begin_test_step("Create ISA") + + with self.check("ISA created", [self._dss.participant_id]) as check: + isa_change = self._dss_wrapper.put_isa( + main_check=check, + area_vertices=self._isa_area, + 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=self._isa_version, + alt_lo=self._isa.altitude_min, + alt_hi=self._isa.altitude_max, ) + self._isa_version = isa_change.dss_query.isa.version - with self.check("ISA ID matches", [self._dss.participant_id]) as check: - if isa_change.dss_query.isa.id != self._isa_id: - check.record_failed( - f"PUT ISA returned ISA with incorrect ID", - Severity.High, - f"DSS should have recorded and returned the ISA ID {self._isa_id} as requested in the path, but response body instead specified {isa_change.dss_query.isa.id}", - query_timestamps=[t_dss], - ) - with self.check("ISA URL matches", [self._dss.participant_id]) as check: - expected_flights_url = self._dss.rid_version.flights_url_of( - self._isa.base_url - ) - actual_flights_url = isa_change.dss_query.isa.flights_url - if actual_flights_url != expected_flights_url: - check.record_failed( - f"PUT ISA returned ISA with incorrect URL", - Severity.High, - f"DSS should have returned an ISA with a flights URL of {expected_flights_url}, but instead the ISA returned had a flights URL of {actual_flights_url}", - query_timestamps=[t_dss], - ) - with self.check("ISA start time matches", [self._dss.participant_id]) as check: - if ( - abs((isa_change.dss_query.isa.time_start - start_time).total_seconds()) - > MAX_SKEW - ): - check.record_failed( - "PUT ISA returned ISA with incorrect start time", - Severity.High, - f"DSS should have returned an ISA with a start time of {start_time}, but instead the ISA returned had a start time of {isa_change.dss_query.isa.time_start}", - query_timestamps=[t_dss], - ) - with self.check("ISA end time matches", [self._dss.participant_id]) as check: - if ( - abs((isa_change.dss_query.isa.time_end - end_time).total_seconds()) - > MAX_SKEW - ): - check.record_failed( - "PUT ISA returned ISA with incorrect end time", - Severity.High, - f"DSS should have returned an ISA with an end time of {end_time}, but instead the ISA returned had an end time of {isa_change.dss_query.isa.time_end}", - query_timestamps=[t_dss], - ) - with self.check("ISA version format", [self._dss.participant_id]) as check: - if not all( - c not in "\0\t\r\n#%/:?@[\]" for c in isa_change.dss_query.isa.version - ): - check.record_failed( - "PUT ISA returned ISA with invalid version format", - Severity.High, - f"DSS returned an ISA with a version that is not URL-safe: {isa_change.dss_query.isa.version}", - query_timestamps=[t_dss], - ) + self.end_test_step() - with self.check("ISA response format", [self._dss.participant_id]) as check: - errors = schema_validation.validate( - self._dss.rid_version.openapi_path, - self._dss.rid_version.openapi_put_isa_response_path, - isa_change.dss_query.query.response.json, - ) - if errors: - details = "\n".join(f"[{e.json_path}] {e.message}" for e in errors) - check.record_failed( - "PUT ISA response format was invalid", - Severity.Medium, - "Found the following schema validation errors in the DSS response:\n" - + details, - query_timestamps=[t_dss], - ) + _create_isa_step() - # TODO: Validate subscriber notifications + self._get_isa_by_id_step() - self.end_test_step() + self.end_test_case() def _update_and_search_isa_case(self): self.begin_test_case("Update and search ISA") diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_validation.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_validation.py index 1c89883739..fda32ab3e3 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_validation.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_validation.py @@ -81,7 +81,7 @@ def _clean_any_sub(self): "Successful subscription query", [self._dss.participant_id] ) as check: fetched = self._dss_wrapper.search_subs( - check, self._isa.footprint.to_vertices() + check, [vertex.as_s2sphere() for vertex in self._isa.footprint] ) for sub_id in fetched.subscriptions.keys(): with self.check( @@ -232,7 +232,7 @@ def _check_properly_truncated( def _default_subscription_params(self, duration: datetime.timedelta) -> Dict: now = datetime.datetime.utcnow() return dict( - area_vertices=self._isa.footprint.to_vertices(), + area_vertices=[vertex.as_s2sphere() for vertex in self._isa.footprint], alt_lo=self._isa.altitude_min, alt_hi=self._isa.altitude_max, start_time=now, diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss_interoperability.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss_interoperability.py index 38ad78a2b4..e75af70b06 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss_interoperability.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss_interoperability.py @@ -27,14 +27,14 @@ def _default_params(duration: datetime.timedelta) -> Dict: - now = datetime.datetime.utcnow() + now = datetime.datetime.now().astimezone() return dict( area_vertices=VERTICES, alt_lo=20, alt_hi=400, start_time=now, end_time=now + duration, - uss_base_url="https://example.com/uss/flights", + uss_base_url="https://example.com", ) diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/dss_wrapper.py b/monitoring/uss_qualifier/scenarios/astm/netrid/dss_wrapper.py index 3c85f041e1..32b9dca914 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/dss_wrapper.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/dss_wrapper.py @@ -3,12 +3,14 @@ from typing import Optional, List, Set +from monitoring.monitorlib import schema_validation from monitoring.monitorlib.fetch import QueryError from monitoring.monitorlib.fetch.rid import ( FetchedSubscription, FetchedSubscriptions, RIDQuery, FetchedISA, + FetchedISAs, ) from monitoring.monitorlib.mutate import rid as mutate from monitoring.monitorlib.fetch import rid as fetch @@ -20,10 +22,14 @@ TestScenario, ) +MAX_SKEW = 1e-6 # seconds maximum difference between expected and actual timestamps + class DSSWrapper(object): """Wraps a DSS instance with test checks.""" + # TODO: adapt other functions with corresponding test step and sub-checks like it is done for put_isa + _scenario: TestScenario _dss: DSSInstance @@ -47,6 +53,7 @@ def base_url(self) -> str: def has_private_address(self) -> bool: return self._dss.has_private_address + # TODO: QueryError is not actually raised for RID functions, this function and its uses should be removed def _handle_query_error( self, check: PendingCheck, @@ -131,7 +138,7 @@ def get_isa( def put_isa( self, - check: PendingCheck, + main_check: PendingCheck, area_vertices: List[s2sphere.LatLng], alt_lo: float, alt_hi: float, @@ -142,70 +149,135 @@ def put_isa( isa_version: Optional[str] = None, ) -> ISAChange: """Create or update an ISA at the DSS. - A check fail is considered of high severity and as such will raise a ScenarioCannotContinueError. - Fails if the ID of the ISA returned by the DSS does not match the submitted one. - Fails if the end time of the ISA returned by the DSS does not match the submitted one. + + Query failure will fail the provided main check. If the query is successful, the sub-checks of the test step + described in '[v19|v22a]/dss/test_steps/put_isa.md' are performed. Some of those might fail the main check. :return: the DSS response """ - try: - mutated_isa = mutate.put_isa( - area_vertices=area_vertices, - alt_lo=alt_lo, - alt_hi=alt_hi, - start_time=start_time, - end_time=end_time, - uss_base_url=uss_base_url, - isa_id=isa_id, - isa_version=isa_version, - rid_version=self._dss.rid_version, - utm_client=self._dss.client, - server_id=self._dss.participant_id, - ) + mutated_isa = mutate.put_isa( + area_vertices=area_vertices, + alt_lo=alt_lo, + alt_hi=alt_hi, + start_time=start_time, + end_time=end_time, + uss_base_url=uss_base_url, + isa_id=isa_id, + isa_version=isa_version, + rid_version=self._dss.rid_version, + utm_client=self._dss.client, + server_id=self._dss.participant_id, + ) + self._handle_query_result( + main_check, mutated_isa.dss_query, f"Failed to insert ISA {isa_id}" + ) + for notification_query in mutated_isa.notifications.values(): + self._scenario.record_query(notification_query.query) + + dss_id = [self._dss.participant_id] + t_dss = mutated_isa.dss_query.query.request.timestamp + dss_isa = mutated_isa.dss_query.isa + + # sub-checks that do not fail the main check + with self._scenario.check("ISA response code", dss_id) as sub_check: + if mutated_isa.dss_query.query.status_code == 201: + sub_check.record_failed( + summary=f"PUT ISA returned technically-incorrect 201", + severity=Severity.Low, + details="DSS should return 200 from PUT ISA, but instead returned the reasonable-but-technically-incorrect code 201", + query_timestamps=[t_dss], + ) - self._handle_query_result( - check, mutated_isa.dss_query, f"Failed to insert ISA {isa_id}" + with self._scenario.check("ISA response format", dss_id) as sub_check: + errors = schema_validation.validate( + self._dss.rid_version.openapi_path, + self._dss.rid_version.openapi_put_isa_response_path, + mutated_isa.dss_query.query.response.json, ) + if errors: + details = "\n".join(f"[{e.json_path}] {e.message}" for e in errors) + sub_check.record_failed( + "PUT ISA response format was invalid", + Severity.Medium, + "Found the following schema validation errors in the DSS response:\n" + + details, + query_timestamps=[t_dss], + ) - dt = abs( - mutated_isa.dss_query.isa.time_end.timestamp() - end_time.timestamp() + # sub-checks that fail the main check + def _fail_sub_check( + _sub_check: PendingCheck, _summary: str, _details: str + ) -> None: + """Fails with Medium severity the sub_check and with High severity the main check.""" + + _sub_check.record_failed( + summary=_summary, + severity=Severity.Medium, + details=_details, + query_timestamps=[t_dss], ) - if dt > 0.001: - check.record_failed( - summary=f"DSS did not correctly create or update ISA; mismatched end time", - severity=Severity.Medium, - participants=[self._dss.participant_id], - details=f"Expected: '{end_time}', received: '{mutated_isa.dss_query.isa.time_end}'", - query_timestamps=[mutated_isa.dss_query.query.request.timestamp], + main_check.record_failed( + summary=f"PUT ISA request succeeded, but the DSS response is not valid: {_summary}", + severity=Severity.High, + details=_details, + query_timestamps=[t_dss], + ) + + with self._scenario.check("ISA ID matches", dss_id) as sub_check: + if isa_id != dss_isa.id: + _fail_sub_check( + sub_check, + "DSS did not return correct ISA", + f"Expected ISA ID {isa_id} but got {dss_isa.id}", ) - elif isa_id != mutated_isa.dss_query.isa.id: - check.record_failed( - summary=f"DSS did not return correct ISA", - severity=Severity.High, - participants=[self._dss.participant_id], - details=f"Expected ISA ID {isa_id} but got {mutated_isa.dss_query.isa.id}", - query_timestamps=[mutated_isa.dss_query.query.request.timestamp], + + if isa_version is not None: + with self._scenario.check("ISA version changed", dss_id) as sub_check: + if dss_isa.version == isa_version: + _fail_sub_check( + sub_check, + "ISA was not modified", + f"Got old version {isa_version} while expecting new version", + ) + + with self._scenario.check("ISA version format", dss_id) as sub_check: + if not all(c not in "\0\t\r\n#%/:?@[\]" for c in dss_isa.version): + _fail_sub_check( + sub_check, + f"DSS returned ISA (ID {isa_id}) with invalid version format", + f"DSS returned an ISA with a version that is not URL-safe: {dss_isa.version}", ) - elif ( - isa_version is not None - and mutated_isa.dss_query.isa.version == isa_version - ): - check.record_failed( - summary=f"ISA was not modified", - severity=Severity.High, - participants=[self._dss.participant_id], - details=f"Got old version {isa_version} while expecting new version", - query_timestamps=[mutated_isa.dss_query.query.request.timestamp], + + with self._scenario.check("ISA start time matches", dss_id) as sub_check: + if abs((dss_isa.time_start - start_time).total_seconds()) > MAX_SKEW: + _fail_sub_check( + sub_check, + f"DSS returned ISA (ID {isa_id}) with incorrect start time", + f"DSS should have returned an ISA with a start time of {start_time}, but instead the ISA returned had a start time of {dss_isa.time_start}", ) - else: - return mutated_isa - except QueryError as e: - self._handle_query_error(check, e) - raise RuntimeError( - "DSS query was not successful, but a High Severity issue didn't interrupt execution" - ) + with self._scenario.check("ISA end time matches", dss_id) as sub_check: + if abs((dss_isa.time_end - end_time).total_seconds()) > MAX_SKEW: + _fail_sub_check( + sub_check, + f"DSS returned ISA (ID {isa_id}) with incorrect end time", + f"DSS should have returned an ISA with an end time of {end_time}, but instead the ISA returned had an end time of {dss_isa.time_end}", + ) + + with self._scenario.check("ISA URL matches", dss_id) as sub_check: + expected_flights_url = self._dss.rid_version.flights_url_of(uss_base_url) + actual_flights_url = dss_isa.flights_url + if actual_flights_url != expected_flights_url: + _fail_sub_check( + sub_check, + f"DSS returned ISA (ID {isa_id}) with incorrect URL", + f"DSS should have returned an ISA with a flights URL of {expected_flights_url}, but instead the ISA returned had a flights URL of {actual_flights_url}", + ) + + # TODO: Validate subscriber notifications + + return mutated_isa def del_isa( self, 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 b34b4d2c7c..a3a46b4509 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/__init__.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/__init__.py @@ -1,2 +1,3 @@ +from .isa_simple import ISASimple from .subscription_validation import SubscriptionValidation from .crdb_access import CRDBAccess diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_simple.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_simple.md new file mode 100644 index 0000000000..a1cce5c6d5 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_simple.md @@ -0,0 +1,84 @@ +# ASTM NetRID DSS: Simple ISA test scenario + +## Overview + +Perform basic operations on a single DSS instance to create an ISA and query it during its time of applicability and +after its time of applicability. + +## 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. + +## Create and check ISA test case + +### [Create ISA test step](test_steps/put_isa.md) + +This step attempts to query the configured DSS with the ISA provided as a resource. + +#### ISA created check + +If the ISA cannot be created, the PUT DSS endpoint in **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** is likely not implemented correctly. + +### Get ISA by ID test step + +This step attempts to retrieve the previously created ISA from the DSS. + +#### Successful ISA query check + +If the ISA cannot be queried, the GET ISA DSS endpoint in **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** is likely not implemented correctly. + +The DSS returns the ID of the ISA in the response body. If this ID does not match the ID in the resource path, **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** was not implemented correctly and this check will fail. + +#### ISA version match check + +The DSS returns the version of the ISA in the response body. If this version does not match the version that was returned after creation, and that no modification of the ISA occurred in the meantime, **[astm.f3411.v19.DSS0030](../../../../../requirements/astm/f3411/v19.md)** was not implemented correctly and this check will fail. + + +## Update and search ISA test case + +## Delete ISA test case + +## 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_simple.py b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_simple.py new file mode 100644 index 0000000000..05ea63b606 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_simple.py @@ -0,0 +1,8 @@ +from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss.isa_simple import ( + ISASimple as CommonISASimple, +) +from monitoring.uss_qualifier.scenarios.scenario import TestScenario + + +class ISASimple(TestScenario, CommonISASimple): + pass diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/test_steps/put_isa.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/test_steps/put_isa.md new file mode 100644 index 0000000000..cddd227af7 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/test_steps/put_isa.md @@ -0,0 +1,36 @@ +# Create or update ISA test step + +This page describes the content of a common test step where a creation or an update of an ISA should be successful. +See `DSSWrapper.put_isa` in [`dss_wrapper.py`](../../../dss_wrapper.py). + +## ISA response code check + +The API for **[astm.f3411.v19.DSS0030](../../../../../../requirements/astm/f3411/v19.md)** specifies that the code of successful DSS responses is 200. While tolerated in some cases, if the DSS responds with an HTTP code 201 for success, this check will fail with a low severity. + +## ISA response format check + +The API for **[astm.f3411.v19.DSS0030](../../../../../../requirements/astm/f3411/v19.md)** specifies an explicit format that the DSS responses must follow. If the DSS response does not validate against this format, this check will fail. + +## ISA ID matches check + +When the ISA is created, the DSS returns the ID of the ISA in the response body. If this ID does not match the ID in the resource path, **[astm.f3411.v19.DSS0030](../../../../../../requirements/astm/f3411/v19.md)** was not implemented correctly and this check will fail. + +## ISA version changed check + +When the ISA is updated, the DSS returns the updated version of the ISA in the response body. If this version remains the same as the one before the update, **[astm.f3411.v19.DSS0030](../../../../../../requirements/astm/f3411/v19.md)** was not implemented correctly and this check will fail. + +## ISA version format check + +Because the ISA version must be used in URLs, it must be URL-safe even though the ASTM standards do not explicitly require this. If the indicated ISA version is not URL-safe, this check will fail. + +## ISA start time matches check + +The ISA creation request specified an exact start time slightly past now, so the DSS should have created an ISA starting at exactly that time. If the DSS response indicates the ISA start time is not this value, **[astm.f3411.v19.DSS0030](../../../../../../requirements/astm/f3411/v19.md)** is not implemented correctly and this check will fail. + +## ISA end time matches check + +The ISA creation request specified an exact end time, so the DSS should have created an ISA ending at exactly that time. If the DSS response indicates the ISA end time is not this value, **[astm.f3411.v19.DSS0030](../../../../../../requirements/astm/f3411/v19.md)** is not implemented correctly and this check will fail. + +## ISA URL matches check + +When the ISA is created, the DSS returns the URL of the ISA in the response body. If this URL does not match the URL requested, **[astm.f3411.v19.DSS0030](../../../../../../requirements/astm/f3411/v19.md)** is not implemented correctly and this check will fail. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss_interoperability.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss_interoperability.md index f822ff8e74..4207b79a8d 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss_interoperability.md +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss_interoperability.md @@ -52,7 +52,7 @@ As such, this check will fail if the DSS is not reachable with a dummy query, ## Interoperability sequence test case -### S1 test step +### [S1 test step](dss/test_steps/put_isa.md) Action: USS1@DSS*P*: PUT ISA with no start time and end time 10 minutes from now @@ -136,7 +136,7 @@ Qualitatively proves: All Subscription[i] 1≤i≤n are returned in subscription **[astm.f3411.v19.DSS0070](../../../../requirements/astm/f3411/v19.md)** requires that all DSS instances in a pool return the same result. This check fails if the DSS instance does not return the same result as the other DSS instances. -### S5 test step +### [S5 test step](dss/test_steps/put_isa.md) Action: USS1@DSS*P*: PUT ISA[*P*] setting end time to now + D seconds @@ -210,7 +210,7 @@ Qualitatively proves: Expired ISA automatically removed, ISA modifications acces **[astm.f3411.v19.DSS0070](../../../../requirements/astm/f3411/v19.md)** requires that all DSS instances in a pool return the same result. This check fails if the DSS instance does not return the same result as the other DSS instances. -### S10 test step +### [S10 test step](dss/test_steps/put_isa.md) Action: USS1@DSS*P*: PUT ISA with no start time and end time 10 minutes from now @@ -238,7 +238,7 @@ Qualitatively proves: ISA deletion triggers subscription notification requests **[astm.f3411.v19.A2-6-1,3c](../../../../requirements/astm/f3411/v19.md)** -### S12 test step +### [S12 test step](dss/test_steps/put_isa.md) Action: Wait >D seconds from S9 then USS1@DSS*P*: PUT ISA with no start time and end time 10 minutes from now diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_simple.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_simple.md index 258ca0c526..c0fee7ad4b 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_simple.md +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_simple.md @@ -40,37 +40,28 @@ When a pre-existing ISA needs to be deleted to ensure a clean workspace, any sub ## Create and check ISA test case -### Create ISA test step +### [Create ISA test step](test_steps/put_isa.md) -This step attempts to create an ISA with a 60-minute expiration. +This step attempts to query the configured DSS with the ISA provided as a resource. #### ISA created check If the ISA cannot be created, the PUT DSS endpoint in **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** is likely not implemented correctly. -#### ISA ID matches check +### Get ISA by ID test step -When the ISA is created, the DSS returns the ID of the ISA in the response body. If this ID does not match the ID in the resource path, **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** was not implemented correctly and this check will fail. +This step attempts to retrieve the previously created ISA from the DSS. -#### ISA URL matches check - -When the ISA is created, the DSS returns the URL of the ISA in the response body. If this URL does not match the URL requested, **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** is not implemented correctly and this check will fail. - -#### ISA start time matches check - -The ISA creation request specified an exact start time slightly past now, so the DSS should have created an ISA starting at exactly that time. If the DSS response indicates the ISA start time is not this value, **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** is not implemented correctly and this check will fail. - -#### ISA end time matches check +#### Successful ISA query check -The ISA creation request specified an exact end time, so the DSS should have created an ISA ending at exactly that time. If the DSS response indicates the ISA end time is not this value, **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** is not implemented correctly and this check will fail. +If the ISA cannot be queried, the GET ISA DSS endpoint in **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** is likely not implemented correctly. -#### ISA version format check +The DSS returns the ID of the ISA in the response body. If this ID does not match the ID in the resource path, **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** was not implemented correctly and this check will fail. -Because the ISA version must be used in URLs, it must be URL-safe even though the ASTM standards do not explicitly require this. If the indicated ISA version is not URL-safe, this check will fail. +#### ISA version match check -#### ISA response format check +The DSS returns the version of the ISA in the response body. If this version does not match the version that was returned after creation, and that no modification of the ISA occurred in the meantime, **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** was not implemented correctly and this check will fail. -The API for **[astm.f3411.v22a.DSS0030](../../../../../requirements/astm/f3411/v22a.md)** specifies an explicit format that the DSS responses must follow. If the DSS response does not validate against this format, this check will fail. ## Update and search ISA test case @@ -86,8 +77,8 @@ The cleanup phase of this test scenario attempts to remove the ISA if the test e ### 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. +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)**. +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/test_steps/put_isa.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/test_steps/put_isa.md new file mode 100644 index 0000000000..495959a7d8 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/test_steps/put_isa.md @@ -0,0 +1,36 @@ +# Create or update ISA test step + +This page describes the content of a common test step where a creation or an update of an ISA should be successful. +See `DSSWrapper.put_isa` in [`dss_wrapper.py`](../../../dss_wrapper.py). + +## ISA response code check + +The API for **[astm.f3411.v22a.DSS0030](../../../../../../requirements/astm/f3411/v22a.md)** specifies that the code of successful DSS responses is 200. While tolerated in some cases, if the DSS responds with an HTTP code 201 for success, this check will fail with a low severity. + +## ISA response format check + +The API for **[astm.f3411.v22a.DSS0030](../../../../../../requirements/astm/f3411/v22a.md)** specifies an explicit format that the DSS responses must follow. If the DSS response does not validate against this format, this check will fail. + +## ISA ID matches check + +When the ISA is created, the DSS returns the ID of the ISA in the response body. If this ID does not match the ID in the resource path, **[astm.f3411.v22a.DSS0030](../../../../../../requirements/astm/f3411/v22a.md)** was not implemented correctly and this check will fail. + +## ISA version changed check + +When the ISA is updated, the DSS returns the updated version of the ISA in the response body. If this version remains the same as the one before the update, **[astm.f3411.v22a.DSS0030](../../../../../../requirements/astm/f3411/v22a.md)** was not implemented correctly and this check will fail. + +## ISA version format check + +Because the ISA version must be used in URLs, it must be URL-safe even though the ASTM standards do not explicitly require this. If the indicated ISA version is not URL-safe, this check will fail. + +## ISA start time matches check + +The ISA creation request specified an exact start time slightly past now, so the DSS should have created an ISA starting at exactly that time. If the DSS response indicates the ISA start time is not this value, **[astm.f3411.v22a.DSS0030](../../../../../../requirements/astm/f3411/v22a.md)** is not implemented correctly and this check will fail. + +## ISA end time matches check + +The ISA creation request specified an exact end time, so the DSS should have created an ISA ending at exactly that time. If the DSS response indicates the ISA end time is not this value, **[astm.f3411.v22a.DSS0030](../../../../../../requirements/astm/f3411/v22a.md)** is not implemented correctly and this check will fail. + +## ISA URL matches check + +When the ISA is created, the DSS returns the URL of the ISA in the response body. If this URL does not match the URL requested, **[astm.f3411.v22a.DSS0030](../../../../../../requirements/astm/f3411/v22a.md)** is not implemented correctly and this check will fail. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss_interoperability.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss_interoperability.md index 85898a4f18..7d67f67959 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss_interoperability.md +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss_interoperability.md @@ -51,7 +51,7 @@ As such, this check will fail if the DSS is not reachable with a dummy query, ## Interoperability sequence test case -### S1 test step +### [S1 test step](dss/test_steps/put_isa.md) Action: USS1@DSS*P*: PUT ISA with no start time and end time 10 minutes from now @@ -135,7 +135,7 @@ Qualitatively proves: All Subscription[i] 1≤i≤n are returned in subscription **[astm.f3411.v22a.DSS0070](../../../../requirements/astm/f3411/v22a.md)** requires that all DSS instances in a pool return the same result. This check fails if the DSS instance does not return the same result as the other DSS instances. -### S5 test step +### [S5 test step](dss/test_steps/put_isa.md) Action: USS1@DSS*P*: PUT ISA[*P*] setting end time to now + D seconds @@ -209,7 +209,7 @@ Qualitatively proves: Expired ISA automatically removed, ISA modifications acces **[astm.f3411.v22a.DSS0070](../../../../requirements/astm/f3411/v22a.md)** requires that all DSS instances in a pool return the same result. This check fails if the DSS instance does not return the same result as the other DSS instances. -### S10 test step +### [S10 test step](dss/test_steps/put_isa.md) Action: USS1@DSS*P*: PUT ISA with no start time and end time 10 minutes from now @@ -237,7 +237,7 @@ Qualitatively proves: ISA deletion triggers subscription notification requests **[astm.f3411.v22a.A2-6-1,3c](../../../../requirements/astm/f3411/v22a.md)** -### S12 test step +### [S12 test step](dss/test_steps/put_isa.md) Action: Wait >D seconds from S9 then USS1@DSS*P*: PUT ISA with no start time and end time 10 minutes from now diff --git a/monitoring/uss_qualifier/suites/astm/netrid/f3411_19.md b/monitoring/uss_qualifier/suites/astm/netrid/f3411_19.md index 848c4e58d2..f6a382650f 100644 --- a/monitoring/uss_qualifier/suites/astm/netrid/f3411_19.md +++ b/monitoring/uss_qualifier/suites/astm/netrid/f3411_19.md @@ -23,7 +23,7 @@ Checked in - astm
.f3411
.v19
+ astm
.f3411
.v19
A2-6-1,1a Implemented ASTM F3411-19 NetRID DSS interoperability @@ -96,7 +96,7 @@ DSS0030 Implemented - ASTM NetRID DSS: Subscription Validation
ASTM NetRID nominal behavior + ASTM F3411-19 NetRID DSS interoperability
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Subscription Validation
ASTM NetRID nominal behavior DSS0050 @@ -276,7 +276,12 @@ NET0710 Implemented - ASTM NetRID nominal behavior + ASTM NetRID DSS: Simple ISA
ASTM NetRID nominal behavior + + + NET0730 + Implemented + ASTM NetRID DSS: Simple ISA interuss
.automated_testing
.rid
.injection
diff --git a/monitoring/uss_qualifier/suites/astm/netrid/f3411_19/dss_probing.md b/monitoring/uss_qualifier/suites/astm/netrid/f3411_19/dss_probing.md index a4a9cff7db..5fcb6823c5 100644 --- a/monitoring/uss_qualifier/suites/astm/netrid/f3411_19/dss_probing.md +++ b/monitoring/uss_qualifier/suites/astm/netrid/f3411_19/dss_probing.md @@ -4,7 +4,8 @@ ## [Actions](../../../README.md#actions) -1. Scenario: [ASTM NetRID DSS: Subscription Validation](../../../../scenarios/astm/netrid/v19/dss/subscription_validation.md) ([`scenarios.astm.netrid.v19.dss.SubscriptionValidation`](../../../../scenarios/astm/netrid/v19/dss/subscription_validation.py)) +1. Scenario: [ASTM NetRID DSS: Simple ISA](../../../../scenarios/astm/netrid/v19/dss/isa_simple.md) ([`scenarios.astm.netrid.v19.dss.ISASimple`](../../../../scenarios/astm/netrid/v19/dss/isa_simple.py)) +2. Scenario: [ASTM NetRID DSS: Subscription Validation](../../../../scenarios/astm/netrid/v19/dss/subscription_validation.md) ([`scenarios.astm.netrid.v19.dss.SubscriptionValidation`](../../../../scenarios/astm/netrid/v19/dss/subscription_validation.py)) ## [Checked requirements](../../../README.md#checked-requirements) @@ -16,10 +17,10 @@ Checked in - astm
.f3411
.v19
+ astm
.f3411
.v19
DSS0030 Implemented - ASTM NetRID DSS: Subscription Validation + ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Subscription Validation DSS0050 @@ -31,4 +32,14 @@ Implemented ASTM NetRID DSS: Subscription Validation + + NET0710 + Implemented + ASTM NetRID DSS: Simple ISA + + + NET0730 + Implemented + ASTM NetRID DSS: Simple ISA + diff --git a/monitoring/uss_qualifier/suites/astm/netrid/f3411_19/dss_probing.yaml b/monitoring/uss_qualifier/suites/astm/netrid/f3411_19/dss_probing.yaml index 13b165753f..8ace89a5e6 100644 --- a/monitoring/uss_qualifier/suites/astm/netrid/f3411_19/dss_probing.yaml +++ b/monitoring/uss_qualifier/suites/astm/netrid/f3411_19/dss_probing.yaml @@ -4,6 +4,12 @@ resources: id_generator: resources.interuss.IDGeneratorResource isa: resources.netrid.ServiceAreaResource actions: + - test_scenario: + scenario_type: scenarios.astm.netrid.v19.dss.ISASimple + resources: + dss: dss + id_generator: id_generator + isa: isa - test_scenario: scenario_type: scenarios.astm.netrid.v19.dss.SubscriptionValidation resources: diff --git a/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a.md b/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a.md index 4958f65391..065a1b97f9 100644 --- a/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a.md +++ b/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a.md @@ -96,7 +96,7 @@ DSS0030 Implemented - ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Subscription Validation
ASTM NetRID nominal behavior + ASTM F3411-22a NetRID DSS interoperability
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Subscription Validation
ASTM NetRID nominal behavior DSS0050 diff --git a/monitoring/uss_qualifier/suites/uspace/network_identification.md b/monitoring/uss_qualifier/suites/uspace/network_identification.md index 3f5d846080..ddee175bc9 100644 --- a/monitoring/uss_qualifier/suites/uspace/network_identification.md +++ b/monitoring/uss_qualifier/suites/uspace/network_identification.md @@ -89,7 +89,7 @@ DSS0030 Implemented - ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Subscription Validation
ASTM NetRID nominal behavior + ASTM F3411-22a NetRID DSS interoperability
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Subscription Validation
ASTM NetRID nominal behavior DSS0050 diff --git a/monitoring/uss_qualifier/suites/uspace/required_services.md b/monitoring/uss_qualifier/suites/uspace/required_services.md index 765f47ff7f..ac5f5092ea 100644 --- a/monitoring/uss_qualifier/suites/uspace/required_services.md +++ b/monitoring/uss_qualifier/suites/uspace/required_services.md @@ -90,7 +90,7 @@ DSS0030 Implemented - ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Subscription Validation
ASTM NetRID nominal behavior + ASTM F3411-22a NetRID DSS interoperability
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Subscription Validation
ASTM NetRID nominal behavior DSS0050