Skip to content

Commit

Permalink
Fixing per PR review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
punamverma committed Nov 17, 2023
1 parent fc394fa commit e6cf0f9
Show file tree
Hide file tree
Showing 9 changed files with 507 additions and 87 deletions.
8 changes: 7 additions & 1 deletion monitoring/monitorlib/clients/flight_planning/client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import ABC, abstractmethod
from typing import List, Optional, Union
from typing import Optional, Set

from monitoring.monitorlib.clients.flight_planning.test_preparation import (
TestPreparationActivityResponse,
Expand All @@ -15,6 +15,7 @@
)
from monitoring.monitorlib.fetch import QueryError
from monitoring.monitorlib.geotemporal import Volume4D
from monitoring.uss_qualifier.configurations.configuration import ParticipantID


class PlanningActivityError(QueryError):
Expand All @@ -24,6 +25,11 @@ class PlanningActivityError(QueryError):
class FlightPlannerClient(ABC):
"""Client to interact with a USS as a user performing flight planning activities and as the test director preparing for tests involving flight planning activities."""

def __init__(self, participant_id: ParticipantID):
self.participant_id = participant_id
self.created_flight_ids: Set[str] = set()
super(FlightPlannerClient, self).__init__()

# ===== Emulation of user actions =====

@abstractmethod
Expand Down
5 changes: 4 additions & 1 deletion monitoring/monitorlib/clients/flight_planning/client_scd.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@
from monitoring.monitorlib.fetch import query_and_describe
from monitoring.monitorlib.geotemporal import Volume4D
from monitoring.monitorlib.infrastructure import UTMClientSession
from monitoring.uss_qualifier.configurations.configuration import ParticipantID


class SCDFlightPlannerClient(FlightPlannerClient):
SCD_SCOPE = scd_api_constants.Scope.Inject
_session: UTMClientSession
_plan_statuses: Dict[FlightID, FlightPlanStatus]
participant_id: ParticipantID

def __init__(self, session: UTMClientSession):
def __init__(self, session: UTMClientSession, participant_id: ParticipantID):
super(SCDFlightPlannerClient, self).__init__(participant_id=participant_id)
self._session = session
self._plan_statuses = {}

Expand Down
9 changes: 4 additions & 5 deletions monitoring/monitorlib/clients/flight_planning/client_v1.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import uuid
from typing import Optional, Set
from typing import Optional
from implicitdict import ImplicitDict
from loguru import logger
from monitoring.monitorlib.clients.flight_planning.client import (
FlightPlannerClient,
)
Expand Down Expand Up @@ -31,12 +32,10 @@
class V1FlightPlannerClient(FlightPlannerClient):
_session: UTMClientSession
participant_id: ParticipantID
base_url: str

def __init__(self, session: UTMClientSession, participant_id: ParticipantID):
super(V1FlightPlannerClient, self).__init__(participant_id=participant_id)
self._session = session
self.participant_id = participant_id
self.created_flight_ids: Set[str] = set()

def _inject(
self,
Expand Down Expand Up @@ -221,7 +220,7 @@ def clear_area(self, area: Volume4D) -> TestPreparationActivityResponse:
raise PlanningActivityError(
f"Response to clear area could not be parsed: {str(e)}", query
)

self.created_flight_ids.clear()
if resp.outcome.success:
errors = None
else:
Expand Down
11 changes: 7 additions & 4 deletions monitoring/uss_qualifier/resources/interuss/mock_uss/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
GetLocalityResponse,
PutLocalityRequest,
)
from monitoring.monitorlib.fetch import QueryError, Query
from monitoring.monitorlib.fetch import QueryError
from monitoring.monitorlib.infrastructure import AuthAdapter, UTMClientSession
from monitoring.monitorlib.locality import LocalityCode
from monitoring.monitorlib.scd_automated_testing.scd_injection_api import (
Expand Down Expand Up @@ -47,8 +47,9 @@ def __init__(
self.session = UTMClientSession(base_url, auth_adapter, timeout_seconds)
self.participant_id = participant_id
v1_base_url = base_url + "/flight_planning/v1"
self.session_fp = UTMClientSession(v1_base_url, auth_adapter, timeout_seconds)
self.flight_planner = V1FlightPlannerClient(self.session_fp, participant_id)
self.flight_planner = V1FlightPlannerClient(
UTMClientSession(v1_base_url, auth_adapter, timeout_seconds), participant_id
)

def get_status(self) -> fetch.Query:
return fetch.query_and_describe(
Expand Down Expand Up @@ -86,7 +87,9 @@ def set_locality(self, locality_code: LocalityCode) -> fetch.Query:

# TODO: Add other methods to interact with the mock USS in other ways (like starting/stopping message signing data collection)

def get_interactions(self, from_time: StringBasedDateTime) -> List[Interaction]:
def get_interactions(
self, from_time: StringBasedDateTime
) -> Tuple[List[Interaction], fetch.Query]:
"""
Requesting interuss interactions from mock_uss from a given time till now
Args:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ No notification pushed by control_uss to tested_uss, will ensure that tested_uss
while planning a nearby flight.
If a notification is sent to tested_uss, the precondition for running this scenario will not be satisfied.

### [Test_uss attempts to plan flight 1, expect failure test step](test_steps/plan_flight_intent_expect_failed.md)
### [Tested_uss attempts to plan flight 1, expect failure test step](test_steps/plan_flight_intent_expect_failed.md)
The test driver attempts to plan the flight 1 via the tested_uss. It checks if any conflicts with flight 2
which is of equal priority and came first.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Optional
from loguru import logger
from urllib.parse import urlsplit

from monitoring.monitorlib.clients.flight_planning.client import FlightPlannerClient
from monitoring.uss_qualifier.resources.astm.f3548.v21 import DSSInstanceResource
from monitoring.uss_qualifier.resources.astm.f3548.v21.dss import DSSInstance
from monitoring.uss_qualifier.resources.flight_planning import (
Expand All @@ -9,30 +10,48 @@
from monitoring.uss_qualifier.resources.flight_planning.flight_intent import (
FlightIntent,
)
from monitoring.uss_qualifier.resources.flight_planning.flight_planner import (
FlightPlanner,
)
from monitoring.uss_qualifier.resources.flight_planning.flight_planners import (
FlightPlannerResource,
)

from monitoring.uss_qualifier.scenarios.scenario import (
TestScenario,
)

from monitoring.monitorlib.geotemporal import Volume4DCollection
from monitoring.monitorlib.clients.flight_planning.flight_info import FlightInfo
from monitoring.uss_qualifier.resources.interuss.mock_uss.client import (
MockUSSClient,
MockUSSResource,
)
from monitoring.uss_qualifier.scenarios.astm.utm.data_exchange_validation.test_steps.invalid_op_test_steps import (
InvalidOpIntentSharingValidator,
plan_flight_intent_expect_failed,
)
from monitoring.uss_qualifier.scenarios.astm.utm.test_steps import OpIntentValidator
from monitoring.uss_qualifier.scenarios.astm.utm.data_exchange_validation.test_steps.expected_interactions_test_steps import (
expect_interuss_post_interactions,
expect_interuss_get_interactions,
expect_no_interuss_post_interactions,
)
from monitoring.monitorlib.clients.mock_uss.mock_uss_scd_injection_api import (
MockUssFlightBehavior,
)
from monitoring.uss_qualifier.scenarios.scenario import (
TestScenario,
ScenarioCannotContinueError,
)
from monitoring.uss_qualifier.scenarios.flight_planning.test_steps import (
cleanup_flights_fp_client,
plan_flight,
delete_flight,
)
from implicitdict import StringBasedDateTime
from datetime import datetime


class GetOpResponseDataValidationByUSS(TestScenario):
flight_1: FlightIntent

flight_2: FlightIntent

tested_uss: FlightPlanner
tested_uss_client: FlightPlannerClient
control_uss: MockUSSClient
control_uss_client: FlightPlannerClient
dss: DSSInstance

def __init__(
Expand All @@ -43,16 +62,208 @@ def __init__(
flight_intents: Optional[FlightIntentsResource] = None,
):
super().__init__()
self.tested_uss = tested_uss.flight_planner
self.tested_uss_client = tested_uss.client
self.control_uss = control_uss.mock_uss
self.control_uss_client = control_uss.mock_uss.flight_planner
self.dss = dss.dss

if not flight_intents:
msg = f"No FlightIntentsResource was provided as input to this test, it is assumed that the jurisdiction of the tested USS ({self.tested_uss.config.participant_id}) does not allow any same priority conflicts, execution of the scenario was stopped without failure"
self.record_note(
"Jurisdiction of tested USS does not allow any same priority conflicts",
msg,
)
raise ScenarioCannotContinueError(msg)

_flight_intents = {
k: FlightIntent.from_flight_info_template(v)
for k, v in flight_intents.get_flight_intents().items()
}

extents = []
for intent in _flight_intents.values():
extents.extend(intent.request.operational_intent.volumes)
extents.extend(intent.request.operational_intent.off_nominal_volumes)
self._intents_extent = Volume4DCollection.from_interuss_scd_api(
extents
).bounding_volume.to_f3548v21()

try:
(self.flight_1, self.flight_2,) = (
_flight_intents["flight_1"],
_flight_intents["flight_2"],
)

assert not Volume4DCollection.from_interuss_scd_api(
self.flight_1.request.operational_intent.volumes
).intersects_vol4s(
Volume4DCollection.from_interuss_scd_api(
self.flight_2.request.operational_intent.volumes
)
), "flight_1 and flight_2 must not intersect"

except KeyError as e:
raise ValueError(
f"`{self.me()}` TestScenario requirements for flight_intents not met: missing flight intent {e}"
)
except AssertionError as e:
raise ValueError(
f"`{self.me()}` TestScenario requirements for flight_intents not met: {e}"
)

def run(self, context):
self.begin_test_scenario(context)
pass

self.record_note(
"Tested USS",
f"{self.tested_uss_client.participant_id}",
)
self.record_note(
"Control USS",
f"{self.control_uss_client.participant_id}",
)

self.begin_test_case("Successfully plan flight near an existing flight")
self._tested_uss_plans_deconflicted_flight_near_existing_flight()
self.end_test_case()

self.begin_test_case("Flight planning prevented due to invalid data sharing")
self._tested_uss_unable_to_plan_flight_near_invalid_shared_existing_flight()
self.end_test_case()

self.end_test_scenario()

def _tested_uss_plans_deconflicted_flight_near_existing_flight(self):

with OpIntentValidator(
self,
self.control_uss_client,
self.dss,
"Validate flight 2 sharing",
self._intents_extent,
) as validator:
_, self.flight_2_id = plan_flight(
self,
"Control_uss plans flight 2",
self.control_uss_client,
FlightInfo.from_scd_inject_flight_request(self.flight_2.request),
)

flight_2_oi_ref = validator.expect_shared(self.flight_2.request)

self.begin_test_step(
"Precondition - check tested_uss has no subscription in flight 2 area"
)
# ToDo - Add the test step details
self.end_test_step()

st = StringBasedDateTime(datetime.utcnow())
with OpIntentValidator(
self,
self.tested_uss_client,
self.dss,
"Validate flight 1 sharing",
self._intents_extent,
) as validator:
_, self.flight_1_id = plan_flight(
self,
"Tested_uss plans flight 1",
self.tested_uss_client,
FlightInfo.from_scd_inject_flight_request(self.flight_1.request),
)

flight_1_oi_ref = validator.expect_shared(
self.flight_1.request,
)

control_uss_domain = "{0.scheme}://{0.netloc}/".format(
urlsplit(self.control_uss.base_url)
)
self.begin_test_step("Validate flight2 GET interaction")
# ToDo - Add the test step details
self.end_test_step()

self.begin_test_step("Validate flight1 Notification sent to Control_uss")
# ToDo - Add the test step details
self.end_test_step()

delete_flight(
self, "Delete tested_uss flight", self.tested_uss_client, self.flight_1_id
)
delete_flight(
self, "Delete control_uss flight", self.control_uss_client, self.flight_2_id
)

def _tested_uss_unable_to_plan_flight_near_invalid_shared_existing_flight(self):
req = self.flight_2.request
# Modifying the request with invalid data
behavior = MockUssFlightBehavior(
modify_sharing_methods=["GET", "POST"],
modify_fields={
"reference": {"state": "Flying"},
"details": {"priority": -1},
},
)

flight_info = FlightInfo.from_scd_inject_flight_request(req)
additional_fields = {"behavior": behavior}

with InvalidOpIntentSharingValidator(
self,
self.control_uss_client,
self.dss,
"Validate flight 2 shared operational intent with invalid data",
self._intents_extent,
) as validator:
_, self.flight_2_id = plan_flight(
self,
"Control_uss plans flight 2, sharing invalid operational intent data",
self.control_uss_client,
flight_info,
additional_fields,
)
flight_2_oi_ref = validator.expect_shared_with_invalid_data(req)

self.begin_test_step(
"Precondition - check tested_uss has no subscription in flight 2 area"
)
# ToDo - Add the test step details
self.end_test_step()

st = StringBasedDateTime(datetime.utcnow())
with InvalidOpIntentSharingValidator(
self,
self.tested_uss_client,
self.dss,
"Validate flight 1 not shared by tested_uss",
self._intents_extent,
) as validator:
_, self.flight_1_id = plan_flight_intent_expect_failed(
self,
"Tested_uss attempts to plan flight 1, expect failure",
self.tested_uss_client,
FlightInfo.from_scd_inject_flight_request(self.flight_1.request),
)
validator.expect_not_shared()

control_uss_domain = "{0.scheme}://{0.netloc}/".format(
urlsplit(self.control_uss.base_url)
)
self.begin_test_step("Validate flight 2 GET interaction")
# ToDo - Add the test step details
self.end_test_step()

self.begin_test_step("Validate flight 1 Notification not sent to Control_uss")
# ToDo - Add the test step details
self.end_test_step()

delete_flight(
self, "Delete Control_uss flight", self.control_uss_client, self.flight_2_id
)

def cleanup(self):
self.begin_cleanup()
pass
cleanup_flights_fp_client(
self, (self.control_uss_client, self.tested_uss_client)
),
self.end_cleanup()
Loading

0 comments on commit e6cf0f9

Please sign in to comment.