Skip to content

Commit

Permalink
[uss_qualifier] DSS0210,1d – check that DSS properly propagates a sub…
Browse files Browse the repository at this point in the history
…scription's area (#538)

dss0210 sub area is sync'd
  • Loading branch information
Shastick authored Mar 12, 2024
1 parent da335eb commit 7b93813
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 9 deletions.
58 changes: 58 additions & 0 deletions monitoring/monitorlib/geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ def from_coords(coords: List[Tuple[float, float]]) -> Polygon:
vertices=[LatLngPoint(lat=lat, lng=lng) for (lat, lng) in coords]
)

@staticmethod
def from_latlng_coords(coords: List[LatLng]) -> Polygon:
return Polygon(
vertices=[
LatLngPoint(lat=p.lat().degrees, lng=p.lng().degrees) for p in coords
]
)

@staticmethod
def from_latlng_rect(latlngrect: s2sphere.LatLngRect) -> Polygon:
return Polygon(
Expand Down Expand Up @@ -651,3 +659,53 @@ def generate_slight_overlap_area(in_points: List[LatLng]) -> List[LatLng]:
)

return [overlap_corner, same_lat_point, opposite_corner, same_lng_point]


def generate_area_in_vicinity(
in_points: List[LatLng], relative_distance: float
) -> List[LatLng]:
"""
Takes a list of LatLng points and returns a list of LatLng points that represents
a non-contiguous area in the vicinity of the input.
The returned polygon is built as such:
- draw a line from the center of the input polygon to the first point of the input polygon
- continue on the line for a distance equal to 'relative_distance' multiplied by the distance between the center and the first point
- from this point, draw a square in the direction opposite of the center of the input polygon
The square will have a size comparable to half of the input polygon's diameter.
"""
starting_point = in_points[0] # our starting point

# 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),
)

# Compute the distance between the center and the starting point, as a 2D vector
delta_lat = center.lat().degrees - starting_point.lat().degrees
delta_lng = center.lng().degrees - starting_point.lng().degrees

# Multiply the vector by the relative distance
distance_lat = delta_lat * relative_distance
distance_lng = delta_lng * relative_distance

closest_corner = LatLng.from_degrees(
starting_point.lat().degrees - distance_lat,
starting_point.lng().degrees - distance_lng,
)

same_lat_point = LatLng.from_degrees(
closest_corner.lat().degrees, closest_corner.lng().degrees - delta_lng
)
same_lng_point = LatLng.from_degrees(
closest_corner.lat().degrees - delta_lat, closest_corner.lng().degrees
)

opposite_corner = LatLng.from_degrees(
closest_corner.lat().degrees - delta_lat,
closest_corner.lng().degrees - delta_lng,
)

return [closest_corner, same_lat_point, opposite_corner, same_lng_point]
34 changes: 33 additions & 1 deletion monitoring/monitorlib/geo_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

from s2sphere import LatLng

from monitoring.monitorlib.geo import generate_slight_overlap_area
from monitoring.monitorlib.geo import (
generate_slight_overlap_area,
generate_area_in_vicinity,
)

MAX_DIFFERENCE = 0.001


def _points(in_points: List[Tuple[float, float]]) -> List[LatLng]:
Expand Down Expand Up @@ -34,3 +39,30 @@ def test_generate_slight_overlap_area():
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)])


def _approx_equals(p1: List[LatLng], p2: List[LatLng]) -> bool:
return all([p1[i].approx_equals(p2[i], MAX_DIFFERENCE) for i in range(len(p1))])


def test_generate_area_in_vicinity():
# Square around 0,0 of edge length 2 -> first corner at 1,1. rel_distance of 2:
# expect a 1 by 1 square with the closest corner at 3,3
assert _approx_equals(
generate_area_in_vicinity(_points([(1, 1), (1, -1), (-1, -1), (-1, 1)]), 2),
_points([(3.0, 3.0), (3.0, 4.0), (4.0, 4.0), (4.0, 3.0)]),
)

# Square around 0,0 of edge length 2 -> first corner at 1,-1. rel_distance of 2:
# expect a 1 by 1 square with the closest corner at 3,-3
assert _approx_equals(
generate_area_in_vicinity(_points([(1, -1), (-1, -1), (-1, 1), (1, 1)]), 2),
_points([(3.0, -3.0), (3.0, -4.0), (4.0, -4.0), (4.0, -3.0)]),
)

# Square with diagonal from 0,0 to -1,-1 -> first corner at -1,-1. rel_distance of 2:
# expect a .5 by .5 square with the closest corner at -2,-2
assert _approx_equals(
generate_area_in_vicinity(_points([(-1, -1), (0, -1), (0, 0), (-1, 0)]), 2),
_points([(-2.0, -2.0), (-2.0, -2.5), (-2.5, -2.5), (-2.5, -2.0)]),
)
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,13 @@ either one of the instances at which the subscription was created or the one tha

If the subscription returned by a DSS to which the subscription was synchronized to does not contain the expected notification count,
either one of the instances at which the subscription was created or the one that was queried, may be failing to implement **[astm.f3548.v21.DSS0210,1i](../../../../../../requirements/astm/f3548/v21.md)**.

## 🛑 Secondary DSS returns the subscription in searches for area that contains it check

The secondary DSS should be aware of the subscription's area: when a search query is issued for an area that encompasses the created subscription,
the secondary DSS should return the subscription in its search results. Otherwise, it is in violation of **[astm.f3548.v21.DSS0210,1d](../../../../../../requirements/astm/f3548/v21.md)**.

## 🛑 Secondary DSS does not return the subscription in searches not encompassing the general area of the subscription check

The secondary DSS should be aware of the subscription's area: when a search query is issued for an area not in the vicinity of the created subscription,
the secondary DSS should not return it in its search results. Otherwise, it is in violation of **[astm.f3548.v21.DSS0210,1d](../../../../../../requirements/astm/f3548/v21.md)**.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from uas_standards.astm.f3548.v21.api import Subscription, SubscriptionID
from uas_standards.astm.f3548.v21.constants import Scope

from monitoring.monitorlib import geo
from monitoring.monitorlib.geo import Volume3D
from monitoring.monitorlib.geotemporal import Volume4D
from monitoring.monitorlib.mutate.scd import MutatedSubscription
from monitoring.prober.infrastructure import register_resource_type
Expand Down Expand Up @@ -93,6 +95,26 @@ def __init__(
volume=self._planning_area.volume,
)

# Get a list of vertices enclosing the area
enclosing_area = geo.get_latlngrect_vertices(
geo.make_latlng_rect(self._planning_area_volume4d.volume)
)

self._enclosing_sub_area_volume4d = Volume4D(
volume=Volume3D(
outline_polygon=geo.Polygon.from_latlng_coords(enclosing_area)
)
)

# Get a list of vertices outside the subscription's area
outside_area = geo.generate_area_in_vicinity(enclosing_area, 2)

self._outside_sub_area_volume4d = Volume4D(
volume=Volume3D(
outline_polygon=geo.Polygon.from_latlng_coords(outside_area)
)
)

self._sub_params = self._planning_area.get_new_subscription_params(
subscription_id=self._sub_id,
# Set this slightly in the past: we will update the subscriptions
Expand Down Expand Up @@ -204,20 +226,91 @@ def _create_sub_with_params(self, creation_params: SubscriptionParams):

def _query_secondaries_and_compare(self, expected_sub_params: SubscriptionParams):
for secondary_dss in self._dss_read_instances:
self._validate_sub_from_secondary(
self._validate_get_sub_from_secondary(
secondary_dss=secondary_dss,
expected_sub_params=expected_sub_params,
involved_participants=list(
{self._primary_pid, secondary_dss.participant_id}
),
)
self._validate_sub_area_from_secondary(
secondary_dss=secondary_dss,
expected_sub_id=expected_sub_params.sub_id,
involved_participants=list(
{self._primary_pid, secondary_dss.participant_id}
),
)

def _validate_sub_area_from_secondary(
self,
secondary_dss: DSSInstance,
expected_sub_id: str,
involved_participants: List[str],
):
"""Checks that the secondary DSS is also aware of the proper subscription's area:
- searching for the subscription's area should yield the subscription
- searching outside the subscription's area should not yield the subscription"""

# Query the subscriptions inside the enclosing area
sub_included = secondary_dss.query_subscriptions(
self._enclosing_sub_area_volume4d.to_f3548v21()
)

with self.check(
"Successful subscription search query", secondary_dss.participant_id
) as check:
if sub_included.status_code != 200:
check.record_failed(
"Subscription search query failed",
details=f"Subscription search query failed with status code {sub_included.status_code}",
query_timestamps=[sub_included.request.timestamp],
)

with self.check(
"Secondary DSS returns the subscription in searches for area that contains it",
involved_participants,
) as check:
if expected_sub_id not in sub_included.subscriptions:
check.record_failed(
"Secondary DSS did not return the subscription",
details=f"Secondary DSS did not return the subscription {expected_sub_id} "
f"although the search volume covered the subscription's area",
query_timestamps=[sub_included.request.timestamp],
)

sub_not_included = secondary_dss.query_subscriptions(
self._outside_sub_area_volume4d.to_f3548v21()
)

with self.check(
"Successful subscription search query", secondary_dss.participant_id
) as check:
if sub_not_included.status_code != 200:
check.record_failed(
summary="Subscription search query failed",
details=f"Subscription search query failed with status code {sub_included.status_code}",
query_timestamps=[sub_included.request.timestamp],
)

with self.check(
"Secondary DSS does not return the subscription in searches not encompassing the general area of the subscription",
involved_participants,
) as check:
if expected_sub_id in sub_not_included.subscriptions:
check.record_failed(
summary="Secondary DSS returned the subscription",
details=f"Secondary DSS returned the subscription {expected_sub_id} "
f"although the search volume did not cover the subscription's general area",
query_timestamps=[sub_not_included.request.timestamp],
)

def _validate_sub_from_secondary(
def _validate_get_sub_from_secondary(
self,
secondary_dss: DSSInstance,
expected_sub_params: SubscriptionParams,
involved_participants: List[str],
):
"""Fetches the subscription from the secondary DSS and validates it."""
with self.check(
"Subscription can be found at every DSS",
involved_participants,
Expand Down
7 changes: 6 additions & 1 deletion monitoring/uss_qualifier/suites/astm/utm/dss_probing.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<th><a href="../../README.md#checked-in">Checked in</a></th>
</tr>
<tr>
<td rowspan="15" style="vertical-align:top;"><a href="../../../requirements/astm/f3548/v21.md">astm<br>.f3548<br>.v21</a></td>
<td rowspan="16" style="vertical-align:top;"><a href="../../../requirements/astm/f3548/v21.md">astm<br>.f3548<br>.v21</a></td>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0005,1</a></td>
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/op_intent_ref_access_control.md">ASTM F3548-21 UTM DSS Operational Intent Reference Access Control</a><br><a href="../../../scenarios/astm/utm/dss/subscription_simple.md">ASTM SCD DSS: Subscription Simple</a><br><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a><br><a href="../../../scenarios/astm/utm/dss/subscription_validation.md">ASTM SCD DSS: Subscription Validation</a></td>
Expand Down Expand Up @@ -61,6 +61,11 @@
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a></td>
</tr>
<tr>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0210,1d</a></td>
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a></td>
</tr>
<tr>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0210,1e</a></td>
<td>Implemented</td>
Expand Down
7 changes: 6 additions & 1 deletion monitoring/uss_qualifier/suites/astm/utm/f3548_21.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
<th><a href="../../README.md#checked-in">Checked in</a></th>
</tr>
<tr>
<td rowspan="41" style="vertical-align:top;"><a href="../../../requirements/astm/f3548/v21.md">astm<br>.f3548<br>.v21</a></td>
<td rowspan="42" style="vertical-align:top;"><a href="../../../requirements/astm/f3548/v21.md">astm<br>.f3548<br>.v21</a></td>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0005,1</a></td>
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/prep_planners.md">ASTM F3548 flight planners preparation</a><br><a href="../../../scenarios/astm/utm/op_intent_ref_access_control.md">ASTM F3548-21 UTM DSS Operational Intent Reference Access Control</a><br><a href="../../../scenarios/astm/utm/dss/subscription_simple.md">ASTM SCD DSS: Subscription Simple</a><br><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a><br><a href="../../../scenarios/astm/utm/dss/subscription_validation.md">ASTM SCD DSS: Subscription Validation</a><br><a href="../../../scenarios/astm/utm/off_nominal_planning/down_uss.md">Off-Nominal planning: down USS</a><br><a href="../../../scenarios/astm/utm/off_nominal_planning/down_uss_equal_priority_not_permitted.md">Off-Nominal planning: down USS with equal priority conflicts not permitted</a></td>
Expand Down Expand Up @@ -80,6 +80,11 @@
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a></td>
</tr>
<tr>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0210,1d</a></td>
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a></td>
</tr>
<tr>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0210,1e</a></td>
<td>Implemented</td>
Expand Down
7 changes: 6 additions & 1 deletion monitoring/uss_qualifier/suites/faa/uft/message_signing.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<th><a href="../../README.md#checked-in">Checked in</a></th>
</tr>
<tr>
<td rowspan="41" style="vertical-align:top;"><a href="../../../requirements/astm/f3548/v21.md">astm<br>.f3548<br>.v21</a></td>
<td rowspan="42" style="vertical-align:top;"><a href="../../../requirements/astm/f3548/v21.md">astm<br>.f3548<br>.v21</a></td>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0005,1</a></td>
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/prep_planners.md">ASTM F3548 flight planners preparation</a><br><a href="../../../scenarios/astm/utm/op_intent_ref_access_control.md">ASTM F3548-21 UTM DSS Operational Intent Reference Access Control</a><br><a href="../../../scenarios/astm/utm/dss/subscription_simple.md">ASTM SCD DSS: Subscription Simple</a><br><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a><br><a href="../../../scenarios/astm/utm/dss/subscription_validation.md">ASTM SCD DSS: Subscription Validation</a><br><a href="../../../scenarios/astm/utm/off_nominal_planning/down_uss.md">Off-Nominal planning: down USS</a><br><a href="../../../scenarios/astm/utm/off_nominal_planning/down_uss_equal_priority_not_permitted.md">Off-Nominal planning: down USS with equal priority conflicts not permitted</a></td>
Expand Down Expand Up @@ -63,6 +63,11 @@
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a></td>
</tr>
<tr>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0210,1d</a></td>
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a></td>
</tr>
<tr>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0210,1e</a></td>
<td>Implemented</td>
Expand Down
7 changes: 6 additions & 1 deletion monitoring/uss_qualifier/suites/interuss/dss/all_tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@
<td><a href="../../../scenarios/astm/netrid/v22a/dss/heavy_traffic_concurrent.md">ASTM NetRID DSS: Concurrent Requests</a><br><a href="../../../scenarios/astm/netrid/v22a/dss/isa_expiry.md">ASTM NetRID DSS: ISA Expiry</a><br><a href="../../../scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.md">ASTM NetRID DSS: ISA Subscription Interactions</a><br><a href="../../../scenarios/astm/netrid/v22a/dss/isa_simple.md">ASTM NetRID DSS: Simple ISA</a><br><a href="../../../scenarios/astm/netrid/v22a/dss/isa_validation.md">ASTM NetRID DSS: Submitted ISA Validations</a><br><a href="../../../scenarios/astm/netrid/v22a/dss/subscription_simple.md">ASTM NetRID DSS: Subscription Simple</a><br><a href="../../../scenarios/astm/netrid/v22a/dss/subscription_validation.md">ASTM NetRID DSS: Subscription Validation</a><br><a href="../../../scenarios/astm/netrid/v22a/dss/token_validation.md">ASTM NetRID DSS: Token Validation</a></td>
</tr>
<tr>
<td rowspan="15" style="vertical-align:top;"><a href="../../../requirements/astm/f3548/v21.md">astm<br>.f3548<br>.v21</a></td>
<td rowspan="16" style="vertical-align:top;"><a href="../../../requirements/astm/f3548/v21.md">astm<br>.f3548<br>.v21</a></td>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0005,1</a></td>
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/op_intent_ref_access_control.md">ASTM F3548-21 UTM DSS Operational Intent Reference Access Control</a><br><a href="../../../scenarios/astm/utm/dss/subscription_simple.md">ASTM SCD DSS: Subscription Simple</a><br><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a><br><a href="../../../scenarios/astm/utm/dss/subscription_validation.md">ASTM SCD DSS: Subscription Validation</a></td>
Expand Down Expand Up @@ -448,6 +448,11 @@
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a></td>
</tr>
<tr>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0210,1d</a></td>
<td>Implemented</td>
<td><a href="../../../scenarios/astm/utm/dss/synchronization/subscription_synchronization.md">ASTM SCD DSS: Subscription Synchronization</a></td>
</tr>
<tr>
<td><a href="../../../requirements/astm/f3548/v21.md">DSS0210,1e</a></td>
<td>Implemented</td>
Expand Down
Loading

0 comments on commit 7b93813

Please sign in to comment.