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

[mock_uss] Modify sharing behavior in mock_uss on injection #269

Conversation

punamverma
Copy link
Contributor

This PR adds the ability to modify sharing behavior of mock_uss on injection, as would be needed by negative tests for data validation of SUT.

  1. Created MockUssInjectFlightRequest (subclass of InjectFlightRequest) that enables adding MockUssFlightBehavior for modifying fields while sharing ops using GET or POST request.
  2. Handled the MockUssFlightBehavior in mock uss routes_injection and routes_scdsc to share modified op in GET and POST requests. DSS has the correct operational_intent, its the operational_intent shared with USSes that is modified for the purpose of writing data validation tests.
  3. Added the ability to inject MockUssFlightBehavior through flight_planner's request_flight method.

Copy link
Member

@BenjaminPelletier BenjaminPelletier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to get to bed; more comments tomorrow, but here's what I have so far.

Comment on lines 6 to 8
class MockUssFlightBehavior(ImplicitDict):
modify_sharing_methods: List[str]
modify_fields: dict
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are very important to document as we're essentially establishing a new interface for mock_uss. Also, remember that flight planning is used for many testing activities, not just F3548-21, so we should be more specific about what sharing and field modifications we're making.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added documentation.

@@ -92,7 +97,7 @@ def plan_flight_intent(
scenario: TestScenarioType,
test_step: str,
flight_planner: FlightPlanner,
flight_intent: InjectFlightRequest,
flight_intent: MockUssInjectFlightRequest,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are test steps that are performed mostly with USSs that are not mock_uss instances so callers of this function often will not have an augmented request. The type of this variable should remain InjectFlightRequest, and a MockUssInjectFlightRequest can still be provided for this variable since it is an InjectFlightRequest.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

Comment on lines 3 to 4
import time
from datetime import datetime
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These imports appear unnecessary

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

@@ -45,6 +49,7 @@ def _inject(
flight_id: FlightID,
flight_info: FlightInfo,
execution_style: ExecutionStyle,
mod_flight_behavior: Optional[MockUssFlightBehavior] = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This client is a particular implementation of the generic client -- we shouldn't change method signatures as that will prevent the use of other implementations of the generic client. Instead, it seems reasonable to add an additional_fields: Optional[dict] = None argument to this function in FlightPlannerClient (and therefore here as well) whose fields get added to the request body just before it's dispatched to the remote server. Doing it this way will allow easy adaptation for other implementations of FlightPlannerClient of which there will soon be one more (for flight_planner interface).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added additional_fields.

@punamverma punamverma marked this pull request as draft October 19, 2023 19:11
@punamverma
Copy link
Contributor Author

I have to get to bed; more comments tomorrow, but here's what I have so far.

Thanks for the comments. Sorry, didn't mean to disturb you.

@BenjaminPelletier
Copy link
Member

I have to get to bed; more comments tomorrow, but here's what I have so far.

Thanks for the comments. Sorry, didn't mean to disturb you.

Oh, no, not at all -- I only review when I'm willing to work. Please feel free to push/comment/update/message/etc at any time regardless of time of day. I just usually like providing a complete set of comments, so wanted to explain why this set was not complete (seemed useful to get these out sooner rather than waiting for a complete set)

@punamverma
Copy link
Contributor Author

@BenjaminPelletier I have made changes using additional_fields. Could you please check. Thanks.

@BenjaminPelletier
Copy link
Member

I can help with the merge on this one -- I'll make a PR to your branch

Copy link
Member

@BenjaminPelletier BenjaminPelletier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR both merges main and addresses these comments

@@ -16,6 +20,7 @@ class FlightRecord(ImplicitDict):
op_intent_injection: scd_injection_api.OperationalIntentTestInjection
flight_authorisation: scd_injection_api.FlightAuthorisationData
op_intent_reference: OperationalIntentReference
mod_op_sharing_behavior: Optional[MockUssFlightBehavior]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to retain the capability to omit this field in an output, so we should default this field to None so we can be sure it's always present.

except ValueError as e:
msg = "Create flight {} unable to parse JSON: {}".format(flight_id, e)
return msg, 400
json, code = inject_flight(flight_id, req_body)
return flask.jsonify(json), code


def op_to_share(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is nearly identical to op_intent_from_flightrecord; let's delete this one and just use op_intent_from_flightrecord (we can compute the FlightRecord just a little earlier when this function is currently being used).

response = GetOperationalIntentDetailsResponse(
operational_intent=op_intent_from_flightrecord(flight),
)
response = {"operational_intent": op_intent_from_flightrecord(flight)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no reason to drop typing here -- let's keep this how it was

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I had tried that. But, that lead to validation of the operational_intent as per GetOperationalIntentDetailsResponse. Whereas, we want to have invalid data in our test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Types are validated upon parsing, but not upon construction -- an invalid value can be provided upon construction.

op_intent = OperationalIntent(reference=ref, details=details)
method = "GET"
if "mod_op_sharing_behavior" in flight:
mod_op_sharing_behavior = ImplicitDict.parse(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to parse here; the FlightRecord is already typed such that flight.mod_op_sharing_behavior is a MockUssFlightBehavior

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks. I think I hadn't defaulted to None, as you suggested in an earlier comment, that's why my tests had failed and I put this check.

if method not in mod_op_sharing_behavior.modify_sharing_methods:
return OperationalIntent(reference=ref, details=details)
if mod_op_sharing_behavior.modify_fields is not None:
if "operational_intent_reference" in mod_op_sharing_behavior.modify_fields:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of looking for these fields specifically by name, let's just have modify_fields apply to the entire OperationalIntent -- that's simpler and less brittle.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that leads to validation of the contents for OperationalIntent. We want to have invalid data there. I ll check it with your PR as well. Thanks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would having modify_fields apply directly to OperationalIntent cause validation versus applying to the two member separately?

Copy link
Contributor Author

@punamverma punamverma Oct 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me pull and check, as earlier I tried it, and while running my tests, I had come across validation errors. But, let me pull your PR and check. Could have been some issue with my code. Will check and let you know if I see any issues. Thanks

@@ -0,0 +1,30 @@
from implicitdict import ImplicitDict
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file relates to client behavior of mock_uss; let's put it in monitorlib/clients/mock_uss

return self._inject(str(uuid.uuid4()), flight_info, execution_style)
return self._inject(
str(uuid.uuid4()), flight_info, execution_style, additional_fields
)

def try_update_flight(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems surprising that we would be able to add fields when planning a flight, but not when updating -- let's add additional_fields here.

return op_intent


def mock_uss_flight_behavior_in_req(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functions that are not document and not intended to be used outside the current file should be prefixed with an underscore


def mock_uss_flight_behavior_in_req(
req_body: InjectFlightRequest,
) -> MockUssFlightBehavior:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this function can also return None, the type annotation should be Optional[MockUssFlightBehavior]

if datetime.utcnow() > deadline:
logger.debug(f"Now {datetime.utcnow} Deadline {deadline} ")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utcnow is a function; it seems like you want to invoke it here (and below). Also, there is a log message immediately below; let's add the content there instead of making a new message.

@BenjaminPelletier BenjaminPelletier changed the title Modify sharing behavior in mock_uss on injection [mock_uss] Modify sharing behavior in mock_uss on injection Oct 24, 2023
@BenjaminPelletier BenjaminPelletier merged commit 0b6beea into interuss:main Oct 24, 2023
8 checks passed
github-actions bot added a commit that referenced this pull request Oct 24, 2023
* Modify sharing behavior in mock_uss on injection

* Added additional_fields to InjectFlightRequest

* Fix format

* Added documentation for MockUssFlightBehavior

* Fix format

* Implement PR suggestions

---------

Co-authored-by: Benjamin Pelletier <[email protected]> 0b6beea
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants