From 2abe74afd256db1d1f4bf746f894dbaf33471fbe Mon Sep 17 00:00:00 2001 From: Julien Perrochet Date: Tue, 21 Nov 2023 19:56:29 +0100 Subject: [PATCH] [uss_qualifier] DSS0030 slight overlap subscription interactions --- .../dss/isa_subscription_interactions.py | 40 ++++++++++++++++++ .../scenarios/astm/netrid/common/dss/utils.py | 41 +++++++++++++++++-- .../astm/netrid/common/dss/utils_test.py | 36 ++++++++++++++++ .../v19/dss/isa_subscription_interactions.md | 5 +++ .../v22a/dss/isa_subscription_interactions.md | 5 +++ 5 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils_test.py 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 index 5238934eb7..87df992ac2 100644 --- 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 @@ -35,6 +35,7 @@ def __init__( # sub id is isa_id with last character replaced with '1' # (the generated isa_id ends with a few '0's) self._sub_id = self._isa_id[:-1] + "1" + self._slight_overlap_sub_id = self._isa_id[:-1] + "2" self._isa_version: Optional[str] = None self._isa = isa.specification @@ -42,6 +43,7 @@ def __init__( 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] + self._slight_overlap_area = utils.generate_slight_overlap_area(self._isa_area) def run(self, context: ExecutionContext): self.begin_test_scenario(context) @@ -191,6 +193,41 @@ def _check_subscription_behaviors(self): query_timestamps=[created_subscription.query.request.timestamp], ) + # Create a subscription to the ISA that only barely overlaps with it: + with self.check( + "Create a subscription within the ISA footprint", [self._dss.participant_id] + ) as check: + slight_overlap_subscription = self._dss_wrapper.put_sub( + check=check, + area_vertices=self._slight_overlap_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._slight_overlap_sub_id, + sub_version=None, + ) + + # Check the subscription + with self.check( + "Subscription that only barely overlaps the ISA contains the ISA", + [self._dss.participant_id], + ) as check: + if created_isa.dss_query.isa.id not in [ + isa.id for isa in slight_overlap_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, + ], + ) + # Delete the ISA with self.check( "Delete the ISA", @@ -304,6 +341,9 @@ def _delete_isa_if_exists(self): def _clean_any_sub(self): self._dss_wrapper.cleanup_subs_in_area(self._isa_area) + # Explicitly clean up in the separate area in case the DSS does + # not return that subscription when searching in the ISA's footpring + self._dss_wrapper.cleanup_subs_in_area(self._slight_overlap_area) def cleanup(self): self.begin_cleanup() diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils.py index c33d76e22d..0841a8c4dc 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils.py @@ -1,12 +1,12 @@ from typing import Optional, List +from s2sphere import LatLng + from monitoring.monitorlib.fetch import rid as fetch -from monitoring.monitorlib.geo import LatLngPoint -from monitoring.monitorlib.mutate import rid as mutate from monitoring.monitorlib.infrastructure import UTMClientSession +from monitoring.monitorlib.mutate import rid as mutate from monitoring.monitorlib.rid import RIDVersion from monitoring.uss_qualifier.common_data_definitions import Severity -from monitoring.uss_qualifier.scenarios.astm.netrid.dss_wrapper import DSSWrapper from monitoring.uss_qualifier.scenarios.scenario import GenericTestScenario @@ -67,3 +67,38 @@ def delete_isa_if_exists( f"Attempting to notify subscriber for ISA {isa_id} at {subscriber_url} resulted in {notification.status_code}", query_timestamps=[notification.query.request.timestamp], ) + + +def generate_slight_overlap_area(in_points: List[LatLng]) -> List[LatLng]: + """ + Takes a list of LatLng points and returns a list of LatLng points that represents + a polygon only slightly overlapping with the input, and that is roughly half the diameter of the input. + + The returned polygon is built from the first point of the input, from which a square + is drawn in the direction opposite of the center of the input polygon. + + """ + overlap_corner = in_points[0] # the spot that will have a tiny overlap + + # Compute the center of mass of the input polygon + center = LatLng.from_degrees( + sum([point.lat().degrees for point in in_points]) / len(in_points), + sum([point.lng().degrees for point in in_points]) / len(in_points), + ) + + delta_lat = center.lat().degrees - overlap_corner.lat().degrees + delta_lng = center.lng().degrees - overlap_corner.lng().degrees + + same_lat_point = LatLng.from_degrees( + overlap_corner.lat().degrees, overlap_corner.lng().degrees - delta_lng + ) + same_lng_point = LatLng.from_degrees( + overlap_corner.lat().degrees - delta_lat, overlap_corner.lng().degrees + ) + + opposite_corner = LatLng.from_degrees( + overlap_corner.lat().degrees - delta_lat, + overlap_corner.lng().degrees - delta_lng, + ) + + return [overlap_corner, same_lat_point, opposite_corner, same_lng_point] diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils_test.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils_test.py new file mode 100644 index 0000000000..d785ec15f3 --- /dev/null +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils_test.py @@ -0,0 +1,36 @@ +from typing import List, Tuple + +from s2sphere import LatLng + +from .utils import generate_slight_overlap_area + + +def _points(in_points: List[Tuple[float, float]]) -> List[LatLng]: + return [LatLng.from_degrees(*p) for p in in_points] + + +def test_generate_slight_overlap_area(): + # Square around 0,0 of edge length 2 -> first corner at 1,1 -> expect a square with overlapping corner at 1,1 + assert generate_slight_overlap_area( + _points([(1, 1), (1, -1), (-1, -1), (-1, 1)]) + ) == _points([(1, 1), (1, 2), (2, 2), (2, 1)]) + + # Square with diagonal from 0,0 to 1,1 -> first corner at 1,1 -> expect a square with overlapping corner at 1,1 + assert generate_slight_overlap_area( + _points([(1, 1), (0, 1), (0, 0), (1, 0)]) + ) == _points([(1, 1), (1, 1.5), (1.5, 1.5), (1.5, 1)]) + + # Square with diagonal from 0,0 to -1,-1 -> first corner at -1,-1 -> expect a square with overlapping corner at -1,-1 + assert generate_slight_overlap_area( + _points([(-1, -1), (0, -1), (0, 0), (-1, 0)]) + ) == _points([(-1, -1), (-1, -1.5), (-1.5, -1.5), (-1.5, -1)]) + + # Square with diagonal from 0,0 to -1,1 -> first corner at -1,1 -> expect a square with overlapping corner at -1,0 + assert generate_slight_overlap_area( + _points([(-1, 1), (-1, 0), (0, 0), (0, 1)]) + ) == _points([(-1, 1), (-1, 1.5), (-1.5, 1.5), (-1.5, 1)]) + + # Square with diagonal from 0,0 to 1,-1 -> first corner at 1,-1 -> expect a square with overlapping corner at 1,-1 + assert generate_slight_overlap_area( + _points([(1, -1), (1, 0), (0, 0), (0, -1)]) + ) == _points([(1, -1), (1, -1.5), (1.5, -1.5), (1.5, -1)]) 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 index 6b66615868..851946067c 100644 --- 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 @@ -98,6 +98,11 @@ and return the up-to-date subscription in the response to the query mutating the Failure to do so means that the DSS is not properly implementing **[astm.f3411.v19.DSS0030,a](../../../../../requirements/astm/f3411/v19.md)**. +#### Subscription that only barely overlaps the ISA contains the ISA check + +A subscription that is created for a volume that only barely overlaps with the previously created ISA should still +contain the ISA in the reply from the server, otherwise the DSS does not comply with **[astm.f3411.v19.DSS0030,c](../../../../../requirements/astm/f3411/v19.md)** + #### Delete the ISA check If that ISA cannot be deleted, the **[astm.f3411.v19.DSS0030,d](../../../../../requirements/astm/f3411/v19.md)** requirement to implement the ISA deletion endpoint might not be met. 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 index 526545c24a..4bb6db214c 100644 --- 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 @@ -98,6 +98,11 @@ and return the up-to-date subscription in the response to the query mutating the Failure to do so means that the DSS is not properly implementing **[astm.f3411.v22a.DSS0030,a](../../../../../requirements/astm/f3411/v22a.md)**. +#### Subscription that only barely overlaps the ISA contains the ISA check + +A subscription that is created for a volume that only barely overlaps with the previously created ISA should still +contain the ISA in the reply from the server, otherwise the DSS does not comply with **[astm.f3411.v22a.DSS0030,c](../../../../../requirements/astm/f3411/v22a.md)** + #### Delete the ISA check If that ISA cannot be deleted, the **[astm.f3411.v22a.DSS0030,d](../../../../../requirements/astm/f3411/v22a.md)** requirement to implement the ISA deletion endpoint might not be met.