Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .basedpyright/baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -19721,14 +19721,6 @@
"lineCount": 1
}
},
{
"code": "reportPossiblyUnboundVariable",
"range": {
"startColumn": 16,
"endColumn": 23,
"lineCount": 1
}
},
{
"code": "reportArgumentType",
"range": {
Expand Down
67 changes: 66 additions & 1 deletion monitoring/uss_qualifier/scenarios/astm/utm/evaluation.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,78 @@
from datetime import timedelta
from urllib.parse import urlparse

from uas_standards.astm.f3548.v21.api import OperationalIntentDetails, Volume4D
from uas_standards.astm.f3548.v21.api import (
OperationalIntentDetails,
OperationalIntentReference,
UssAvailabilityState,
Volume4D,
)

from monitoring.monitorlib.geotemporal import Volume4DCollection
from monitoring.monitorlib.scd import priority_of

NUMERIC_PRECISION = 0.001


def validate_op_intent_reference(
uss_oi: OperationalIntentReference,
dss_oi: OperationalIntentReference,
) -> str | None:
# this function assumes all fields required by the OpenAPI definition are present as the format validation
# should have been performed by OpIntentValidator._evaluate_op_intent_validation before
errors_text: list[str] = []

def append_err(name: str, uss_value: str, dss_value: str):
errors_text.append(
f"{name} reported by USS ({uss_value}) does not match the one published to the DSS ({dss_value})"
)
return

if uss_oi.version != dss_oi.version:
append_err("Version", str(uss_oi.version), str(dss_oi.version))
if uss_oi.state != dss_oi.state:
append_err("State", uss_oi.state, dss_oi.state)

# use str.lower() to tolerate case mismatch for string values
if uss_oi.id.lower() != dss_oi.id.lower():
append_err("ID", uss_oi.id, dss_oi.id)
if uss_oi.manager.lower() != dss_oi.manager.lower():
append_err("Manager", uss_oi.manager, dss_oi.manager)
if uss_oi.subscription_id.lower() != dss_oi.subscription_id.lower():
append_err("Subscription ID", uss_oi.subscription_id, dss_oi.subscription_id)
if uss_oi.uss_availability.lower() != dss_oi.uss_availability.lower():
# tolerate empty value if unknown
if (
len(uss_oi.uss_availability) != 0
or dss_oi.uss_availability != UssAvailabilityState.Unknown
):
append_err(
"USS availability", uss_oi.uss_availability, dss_oi.uss_availability
)

if uss_oi.uss_base_url != dss_oi.uss_base_url:
# tolerate differences in URL that have no impact
uss_url = urlparse(uss_oi.uss_base_url)
dss_url = urlparse(dss_oi.uss_base_url)
if (
uss_url.scheme != dss_url.scheme
or uss_url.netloc != dss_url.netloc
or uss_url.path != dss_url.path
):
append_err("USS base URL", uss_oi.uss_base_url, dss_oi.uss_base_url)

if abs(
uss_oi.time_start.value.datetime - dss_oi.time_start.value.datetime
) > timedelta(seconds=NUMERIC_PRECISION):
append_err("Start time", uss_oi.time_start.value, dss_oi.time_start.value)
if abs(uss_oi.time_end.value.datetime - dss_oi.time_end.value.datetime) > timedelta(
seconds=NUMERIC_PRECISION
):
append_err("End time", uss_oi.time_start.value, dss_oi.time_start.value)

return "; ".join(errors_text) if errors_text else None


def validate_op_intent_details(
op_intent_details: OperationalIntentDetails,
expected_priority: int,
Expand Down
17 changes: 17 additions & 0 deletions monitoring/uss_qualifier/scenarios/astm/utm/test_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
)
from monitoring.uss_qualifier.scenarios.astm.utm.evaluation import (
validate_op_intent_details,
validate_op_intent_reference,
)
from monitoring.uss_qualifier.scenarios.scenario import (
ScenarioDidNotStopError,
Expand Down Expand Up @@ -420,6 +421,7 @@ def _check_op_intent_details(
details=f"Received status code {oi_full_query.status_code} from {self._flight_planner.participant_id} when querying for details of operational intent {oi_ref.id}; {e}",
query_timestamps=[oi_full_query.request.timestamp],
)
return

validation_failures = self._evaluate_op_intent_validation(oi_full_query)
with self._scenario.check(
Expand All @@ -444,6 +446,21 @@ def _check_op_intent_details(
query_timestamps=[oi_full_query.request.timestamp],
)

with self._scenario.check(
"Operational intent reference reported by USS matches the one published to the DSS",
[self._flight_planner.participant_id],
) as check:
error_text = validate_op_intent_reference(
oi_full.reference,
oi_ref,
)
if error_text:
check.record_failed(
summary="Operational intent reference reported by USS does not match the one published to the DSS",
details=error_text,
query_timestamps=[oi_full_query.request.timestamp],
)

with self._scenario.check(
"Correct operational intent details", [self._flight_planner.participant_id]
) as check:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ If the operational intent details for the flight cannot be retrieved from the US

If the operational intent details response does not validate against [the GetOperationalIntentDetailsResponse schema of the OpenAPI specification](https://github.com/astm-utm/Protocol/blob/v1.0.0/utm.yaml#L1120), this check fill fail per **[astm.f3548.v21.USS0105,1](../../../requirements/astm/f3548/v21.md)**.

## 🛑 Operational intent reference reported by USS matches the one published to the DSS check

If any of the values in the operational intent reference reported by the USS do not match those values in the operational intent reference published to (and known by) the DSS, save for the OVN, this check will fail per **[astm.f3548.v21.USS0005](../../../requirements/astm/f3548/v21.md)** since the values reported by the USS were not made discoverable via the DSS.

## 🛑 Correct operational intent details check

If the operational intent details reported by the USS do not match the user's flight intent, this check will fail per **[interuss.automated_testing.flight_planning.ExpectedBehavior](../../../requirements/interuss/automated_testing/flight_planning.md)** and **[astm.f3548.v21.OPIN0025](../../../requirements/astm/f3548/v21.md)**.
Expand Down
Loading