diff --git a/monitoring/monitorlib/geo.py b/monitoring/monitorlib/geo.py index f568e0d0d3..b47b483bb2 100644 --- a/monitoring/monitorlib/geo.py +++ b/monitoring/monitorlib/geo.py @@ -7,6 +7,7 @@ from implicitdict import ImplicitDict import numpy as np import s2sphere +from s2sphere import LatLng from scipy.interpolate import RectBivariateSpline as Spline import shapely.geometry from uas_standards.astm.f3548.v21 import api as f3548v21 @@ -501,3 +502,38 @@ def egm96_geoid_offset(p: s2sphere.LatLng) -> float: # listed -90 to 90. Since latitude data are symmetric, we can simply # convert "-90 to 90" to "90 to -90" by inverting the requested latitude. return _egm96.ev(-lat, lng) + + +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/monitorlib/geo_test.py b/monitoring/monitorlib/geo_test.py new file mode 100644 index 0000000000..ba2b52af17 --- /dev/null +++ b/monitoring/monitorlib/geo_test.py @@ -0,0 +1,36 @@ +from typing import List, Tuple + +from s2sphere import LatLng + +from monitoring.monitorlib.geo 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/common/dss/isa_subscription_interactions.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_subscription_interactions.py index 741d57982f..e2e74a6138 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 @@ -2,6 +2,7 @@ import arrow +from monitoring.monitorlib import geo 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 @@ -35,6 +36,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 +44,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 = geo.generate_slight_overlap_area(self._isa_area) def run(self, context: ExecutionContext): self.begin_test_scenario(context) @@ -191,6 +194,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", @@ -305,6 +343,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 036876ed93..54e20a6655 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils.py @@ -1,5 +1,7 @@ from typing import Optional +from s2sphere import LatLng + from monitoring.monitorlib.fetch import rid as fetch from monitoring.monitorlib.infrastructure import UTMClientSession from monitoring.monitorlib.mutate import rid as mutate 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. diff --git a/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a.md b/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a.md index e3f4b1d8b6..fe75a4fa68 100644 --- a/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a.md +++ b/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a.md @@ -497,6 +497,6 @@ SearchISAs Implemented - ASTM NetRID DSS: ISA Expiry
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Token Validation
ASTM NetRID nominal behavior + ASTM NetRID DSS: ISA Expiry
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Token Validation
ASTM NetRID nominal behavior diff --git a/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a/dss_probing.md b/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a/dss_probing.md index e47da15df9..a1a4b7002d 100644 --- a/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a/dss_probing.md +++ b/monitoring/uss_qualifier/suites/astm/netrid/f3411_22a/dss_probing.md @@ -228,6 +228,6 @@ SearchISAs Implemented - ASTM NetRID DSS: ISA Expiry
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Token Validation + ASTM NetRID DSS: ISA Expiry
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Token Validation diff --git a/monitoring/uss_qualifier/suites/interuss/dss/all_tests.md b/monitoring/uss_qualifier/suites/interuss/dss/all_tests.md index b9e5989205..cd5267e269 100644 --- a/monitoring/uss_qualifier/suites/interuss/dss/all_tests.md +++ b/monitoring/uss_qualifier/suites/interuss/dss/all_tests.md @@ -409,6 +409,6 @@ SearchISAs Implemented - ASTM NetRID DSS: ISA Expiry
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Token Validation + ASTM NetRID DSS: ISA Expiry
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Token Validation diff --git a/monitoring/uss_qualifier/suites/uspace/network_identification.md b/monitoring/uss_qualifier/suites/uspace/network_identification.md index c2fb5d1232..a4b7e157a6 100644 --- a/monitoring/uss_qualifier/suites/uspace/network_identification.md +++ b/monitoring/uss_qualifier/suites/uspace/network_identification.md @@ -492,6 +492,6 @@ SearchISAs Implemented - ASTM NetRID DSS: ISA Expiry
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Token Validation
ASTM NetRID nominal behavior + ASTM NetRID DSS: ISA Expiry
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Token Validation
ASTM NetRID nominal behavior diff --git a/monitoring/uss_qualifier/suites/uspace/required_services.md b/monitoring/uss_qualifier/suites/uspace/required_services.md index ed16b729cb..de57d3c942 100644 --- a/monitoring/uss_qualifier/suites/uspace/required_services.md +++ b/monitoring/uss_qualifier/suites/uspace/required_services.md @@ -631,7 +631,7 @@ SearchISAs Implemented - ASTM NetRID DSS: ISA Expiry
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Token Validation
ASTM NetRID nominal behavior + ASTM NetRID DSS: ISA Expiry
ASTM NetRID DSS: Simple ISA
ASTM NetRID DSS: Token Validation
ASTM NetRID nominal behavior interuss
.f3548
.notification_requirements