Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[uss_qualifier] submit_flight_intent test step raises if flight intent ends in the past #650

Merged
merged 2 commits into from
Apr 23, 2024
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
31 changes: 30 additions & 1 deletion monitoring/monitorlib/geotemporal.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import math
from datetime import datetime, timedelta
from typing import Optional, List, Tuple, Dict
from typing import Optional, List, Tuple, Dict, Union

import arrow
from implicitdict import ImplicitDict, StringBasedTimeDelta
import s2sphere as s2sphere

Expand Down Expand Up @@ -427,3 +428,31 @@ def has_active_volume(self, time_ref: datetime) -> bool:

class Volume4DTemplateCollection(List[Volume4DTemplate]):
pass


def end_time_of(
volume_or_volumes: Union[
f3548v21.Volume4D,
Volume4D,
List[Union[f3548v21.Volume4D, Volume4D]],
Volume4DCollection,
]
) -> Optional[Time]:
"""Retrieve the end time of a volume or list of volumes."""
if isinstance(volume_or_volumes, f3548v21.Volume4D):
if "time_end" in volume_or_volumes and volume_or_volumes.time_end:
return Time(volume_or_volumes.time_end.value)
else:
return None
elif isinstance(volume_or_volumes, Volume4D):
return volume_or_volumes.time_end
elif isinstance(volume_or_volumes, Volume4DCollection):
return volume_or_volumes.time_end
elif isinstance(volume_or_volumes, list):
time_ends = [end_time_of(v) for v in volume_or_volumes]
if not time_ends:
return None
elif any(t is None for t in time_ends):
return None
else:
return max(time_ends)
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ def _attempt_invalid(self, times: Dict[TimeDuringTest, Time]):
{PlanningActivityResult.Failed: "Failure"},
self.tested_uss.client,
invalid_recently_ended,
may_end_in_past=True,
)

validator.expect_not_shared()
Expand Down
21 changes: 19 additions & 2 deletions monitoring/uss_qualifier/scenarios/flight_planning/test_steps.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import inspect
from typing import Optional, Tuple, Iterable, Set, Dict, Union

import arrow

from monitoring.monitorlib.geotemporal import end_time_of
from uas_standards.interuss.automated_testing.flight_planning.v1.api import (
BasicFlightPlanInformationUsageState,
BasicFlightPlanInformationUasState,
Expand All @@ -23,8 +26,6 @@
)
from monitoring.monitorlib.fetch import QueryError, Query

from uas_standards.astm.f3548.v21.api import OperationalIntentState

from uas_standards.interuss.automated_testing.scd.v1.api import (
InjectFlightRequest,
InjectFlightResponseResult,
Expand Down Expand Up @@ -260,6 +261,12 @@ def submit_flight_intent(
f"expected and unexpected results overlap: {expected_results.intersection(failed_checks.keys())}"
)

intent_end_time = end_time_of(flight_intent.operational_intent.volumes)
if intent_end_time and intent_end_time.datetime < arrow.utcnow():
raise ValueError(
f"attempt to submit invalid flight intent: end time is in the past: {intent_end_time}"
)

with scenario.check(success_check, [flight_planner.participant_id]) as check:
try:
resp, query, flight_id, advisories = flight_planner.request_flight(
Expand Down Expand Up @@ -492,12 +499,15 @@ def submit_flight(
flight_id: Optional[str] = None,
additional_fields: Optional[dict] = None,
skip_if_not_supported: bool = False,
may_end_in_past: bool = False,
) -> Tuple[PlanningActivityResponse, Optional[str]]:
"""Submit a flight intent with an expected result.
A check fail is considered by default of high severity and as such will raise an ScenarioCannotContinueError.
The severity of each failed check may be overridden if needed.
If skip_if_not_supported=True and the USS responds that the operation is not supported, the check is skipped without failing.

If may_end_in_past=True, this function won't raise an error if the flight intent's end time is in the past.

This function does not directly implement a test step.

Returns:
Expand All @@ -509,6 +519,13 @@ def submit_flight(
f"expected and unexpected results overlap: {expected_results.intersection(failed_checks.keys())}"
)

if not may_end_in_past:
intent_end_time = end_time_of(flight_info.basic_information.area)
if intent_end_time and intent_end_time.datetime < arrow.utcnow():
raise ValueError(
f"attempt to submit invalid flight intent: end time is in the past: {intent_end_time}"
)

with scenario.check(success_check, [flight_planner.participant_id]) as check:
try:
resp, query, flight_id = request_flight(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ intents:
start_time:
offset_from:
starting_from:
time_during_test: StartOfTestRun
time_during_test: StartOfScenario
offset: -1s
duration: 5m

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ intents:
start_time:
offset_from:
starting_from:
time_during_test: StartOfTestRun
time_during_test: StartOfScenario
offset: -1s
duration: 5m
duration: 10m

astm_f3548_21:
priority: 0
Expand All @@ -51,7 +51,7 @@ intents:
- start_time:
offset_from:
starting_from:
time_during_test: StartOfTestRun
time_during_test: StartOfScenario
offset: 32d

invalid_recently_ended:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ intents:
start_time:
offset_from:
starting_from:
time_during_test: StartOfTestRun
time_during_test: StartOfScenario
offset: -1s
duration: 5m

Expand Down Expand Up @@ -59,7 +59,7 @@ intents:
start_time:
offset_from:
starting_from:
time_during_test: StartOfTestRun
time_during_test: StartOfScenario
offset: -1s
duration: 5m

Expand Down
Loading