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] Adding the interactions and invalid op checks steps #376

Merged
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
e2e55c8
Adding the interactions and invalid op checks steps
punamverma Nov 29, 2023
84c59cc
Added mock_uss to prep_planners doc
punamverma Nov 29, 2023
83e1e08
fix format
punamverma Nov 29, 2023
2ddb964
Fix doc
punamverma Nov 29, 2023
1a6622f
Adding missing code
punamverma Nov 29, 2023
ce4488e
Adding missing mock_uss resource to PrepareFlightPlanners
punamverma Nov 30, 2023
2aa5f05
Merge branch 'main' into interactions_and_invalid_op_checks
punamverma Nov 30, 2023
a44b49e
Fix per PR comments
punamverma Dec 1, 2023
907cbfe
Merge branch 'main' into interactions_and_invalid_op_checks
punamverma Dec 1, 2023
c2e8bf6
Merge branch 'main' into interactions_and_invalid_op_checks
punamverma Dec 1, 2023
9687ac2
Removing post check for a particular url
punamverma Dec 1, 2023
83a40d8
Fixing check details
punamverma Dec 1, 2023
3a8bdc4
Adding 5 s back, removing url check no post interactions
punamverma Dec 1, 2023
3df884c
Merge branch 'main' into interactions_and_invalid_op_checks
punamverma Dec 2, 2023
42cceda
Wait only for checking POST notifications
punamverma Dec 2, 2023
8fdcb69
Fix per PR comments
punamverma Dec 4, 2023
8797056
Fix per PR review
punamverma Dec 4, 2023
9abdf23
Fix format
punamverma Dec 4, 2023
fbae1b1
Refactoring code, removed wait time for other than post interactions …
punamverma Dec 6, 2023
40bc79c
querying for interactions optimistically
punamverma Dec 7, 2023
22931da
Merge branch 'main' into interactions_and_invalid_op_checks
punamverma Dec 7, 2023
d282151
Fix passing ref id
punamverma Dec 7, 2023
f892e01
Merge branch 'main' into interactions_and_invalid_op_checks
punamverma Dec 7, 2023
2c7dba1
Update monitoring/uss_qualifier/scenarios/astm/utm/data_exchange_vali…
punamverma Dec 8, 2023
b330dff
Fix per review comments
punamverma Dec 8, 2023
1fcbafa
Fix per review
punamverma Dec 8, 2023
fca841f
Adding missing code for Query
punamverma Dec 8, 2023
688dd4c
Fixed documentation for wait time as per PR comments
punamverma Dec 11, 2023
e9b0566
Merge branch 'main' into interactions_and_invalid_op_checks
punamverma Dec 11, 2023
1405f0e
Adding subscription check with GET request check
punamverma Dec 12, 2023
694ff22
Fixed per PR comments
punamverma Dec 13, 2023
4bcb865
Merge branch 'main' into interactions_and_invalid_op_checks
punamverma Dec 13, 2023
1f588ec
Fix per review
punamverma Dec 14, 2023
75d57b1
Merge branch 'main' into interactions_and_invalid_op_checks
punamverma Dec 14, 2023
62f1155
Removing args from comments
punamverma Dec 14, 2023
844fb4b
Conditional call of GET request based on notification
punamverma Dec 14, 2023
7999f53
Refining check message
punamverma Dec 14, 2023
aa89491
Removing else condition, and renaming test step and check as discussed
punamverma Dec 15, 2023
ee8d6cb
Merge branch 'main' into interactions_and_invalid_op_checks
punamverma Dec 15, 2023
2e4d228
Changing method name per review
punamverma Dec 16, 2023
d09dab5
fixing the condition for GET request check
punamverma Dec 16, 2023
2ce1399
Want to trigger CI run that failed on netrid test
punamverma Dec 16, 2023
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
9 changes: 9 additions & 0 deletions monitoring/monitorlib/clients/flight_planning/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,12 @@ def clear_area(self, area: Volume4D) -> TestPreparationActivityResponse:
* PlanningActivityError
"""
raise NotImplementedError()

@abstractmethod
def get_base_url(self) -> str:
"""
Get the base_url associated with this FlightPlannerClient
Returns:

"""
raise NotImplementedError
3 changes: 3 additions & 0 deletions monitoring/monitorlib/clients/flight_planning/client_scd.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,6 @@ def clear_area(self, area: Volume4D) -> TestPreparationActivityResponse:
errors = [f"[{resp.outcome.timestamp}]: {resp.outcome.message}"]

return TestPreparationActivityResponse(errors=errors, queries=[query])

def get_base_url(self):
return self._session.get_prefix_url()
3 changes: 3 additions & 0 deletions monitoring/monitorlib/clients/flight_planning/client_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,6 @@ def clear_area(self, area: Volume4D) -> TestPreparationActivityResponse:
errors = [resp.outcome.message]

return TestPreparationActivityResponse(errors=errors, queries=[query])

def get_base_url(self):
return self._session.get_prefix_url()
10 changes: 10 additions & 0 deletions monitoring/monitorlib/fetch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import traceback
import uuid
import jwt
from typing import Dict, Optional, List, Union

from enum import Enum
Expand Down Expand Up @@ -290,6 +291,15 @@ def error_message(self) -> Optional[str]:
else None
)

def get_client_sub(self):
headers = self.request.headers
if "Authorization" in headers:
token = headers.get("Authorization").split(" ")[1]
payload = jwt.decode(
token, algorithms="RS256", options={"verify_signature": False}
)
return payload["sub"]


class QueryError(RuntimeError):
"""Error encountered when interacting with a server in the UTM ecosystem."""
Expand Down
40 changes: 31 additions & 9 deletions monitoring/uss_qualifier/resources/astm/f3548/v21/dss.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from __future__ import annotations

import uuid
from typing import Tuple, List, Optional
from urllib.parse import urlparse
from typing import Tuple, List, Dict, Optional

from urllib.parse import urlparse
from implicitdict import ImplicitDict

from monitoring.monitorlib import infrastructure, fetch
Expand Down Expand Up @@ -125,6 +124,31 @@ def get_full_op_intent(
op_intent_ref: OperationalIntentReference,
uss_participant_id: Optional[str] = None,
) -> Tuple[OperationalIntent, fetch.Query]:
result, query = self.get_full_op_intent_without_validation(
op_intent_ref,
uss_participant_id,
)
if query.status_code != 200:
result = None
else:
result = ImplicitDict.parse(
query.response.json, GetOperationalIntentDetailsResponse
).operational_intent
return result, query

def get_full_op_intent_without_validation(
BenjaminPelletier marked this conversation as resolved.
Show resolved Hide resolved
self,
op_intent_ref: OperationalIntentReference,
uss_participant_id: Optional[str] = None,
) -> Tuple[Dict, fetch.Query]:
"""
GET OperationalIntent without validating, as invalid data expected for negative tests
Args:
op_intent_ref:
BenjaminPelletier marked this conversation as resolved.
Show resolved Hide resolved
uss_participant_id:
Returns:
returns the response json when query is successful
"""
url = f"{op_intent_ref.uss_base_url}/uss/v1/operational_intents/{op_intent_ref.id}"
query = fetch.query_and_describe(
BenjaminPelletier marked this conversation as resolved.
Show resolved Hide resolved
self.client,
Expand All @@ -134,12 +158,10 @@ def get_full_op_intent(
uss_participant_id,
scope=SCOPE_SC,
)
if query.status_code != 200:
result = None
else:
result = ImplicitDict.parse(
query.response.json, GetOperationalIntentDetailsResponse
).operational_intent
result = None
if query.status_code == 200:
result = query.response.json

return result, query

def put_op_intent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ Flight 2 should be successfully planned by the control USS.
### [Validate flight 2 sharing test step](../validate_shared_operational_intent.md)
Validate that flight 2 is planned

### Precondition - check tested_uss has no subscription in flight 2 area test step
### Check for notification to tested_uss due to subscription in flight 2 area test step
In order to run this test scenario, we need tested_uss to trigger GET operational intent request to mock_uss.
So we need to make sure that there is no subscription of tested_uss, that would trigger notification of flight 2 to tested_uss.
No notification pushed by control_uss to tested_uss, will ensure that tested_uss will make a GET request to control_uss for flight 2 details,
while planning a nearby flight.
If a notification is sent to tested_uss, the precondition for running this scenario will not be satisfied.
But, if there is a subscription by tested_uss, that would trigger notification of flight 2 to tested_uss.
Some USSes will not make a GET request to control_uss for flight 2 details, while planning a nearby flight,
if they got a notification for flight2. Hence, if a USS didn't make a GET request, we will only fail it if didn't get
a notification, or else, a precondition for the test will not be met.

### [Tested_uss plans flight 1 test step](../../../flight_planning/plan_flight_intent.md)
The test driver attempts to plan flight 1 via the tested USS. It checks if any conflicts with flight 2
Expand Down Expand Up @@ -71,12 +71,12 @@ The control_uss, which is mock_uss is instructed to share invalid data with othe
### [Validate flight 2 shared operational intent with invalid data test step](test_steps/validate_sharing_operational_intent_but_with_invalid_interuss_data.md)
Validate that flight 2 is shared with invalid data as a modified behavior is injected by uss_qualifier for a negative test.

### Precondition - check tested_uss has no subscription in flight 2 area test step
### Check for notification to tested_uss due to subscription in flight 2 area test step
In order to run this test scenario, we need tested_uss to trigger GET operational intent request to mock_uss.
So we need to make sure that there is no subscription of tested_uss, that would trigger notification of flight 2 to tested_uss.
No notification pushed by control_uss to tested_uss, will ensure that tested_uss will make a GET request to control_uss for flight 2 details,
while planning a nearby flight.
If a notification is sent to tested_uss, the precondition for running this scenario will not be satisfied.
But, if there is a subscription by tested_uss, that would trigger notification of flight 2 to tested_uss.
Some USSes will not make a GET request to control_uss for flight 2 details, while planning a nearby flight,
if they got a notification for flight2. Hence, if a USS didn't make a GET request, we will only fail it if didn't get
a notification, or else, a precondition for the test will not be met.

### [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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing import Optional, Dict

from monitoring.monitorlib.clients.flight_planning.flight_info_template import (
FlightInfoTemplate,
)
from monitoring.monitorlib.temporal import TimeDuringTest, Time
from monitoring.monitorlib.temporal import TimeDuringTest
import arrow
from implicitdict import StringBasedDateTime

from monitoring.monitorlib.temporal import Time
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
Expand All @@ -24,8 +25,16 @@
from monitoring.uss_qualifier.scenarios.astm.utm.data_exchange_validation.test_steps.invalid_op_test_steps import (
plan_flight_intent_expect_failed,
)
from monitoring.uss_qualifier.scenarios.astm.utm.test_steps import OpIntentValidator

from monitoring.uss_qualifier.scenarios.astm.utm.test_steps import (
OpIntentValidator,
OpIntentValidationFailureType,
)
from monitoring.uss_qualifier.scenarios.astm.utm.data_exchange_validation.test_steps.expected_interactions_test_steps import (
expect_interuss_post_interactions,
expect_get_requests_to_mock_uss,
expect_no_interuss_post_interactions,
check_any_notification,
)
from monitoring.monitorlib.clients.mock_uss.mock_uss_scd_injection_api import (
MockUssFlightBehavior,
)
Expand Down Expand Up @@ -138,26 +147,32 @@ def _tested_uss_plans_deconflicted_flight_near_existing_flight(
):
times[TimeDuringTest.TimeOfEvaluation] = Time(arrow.utcnow().datetime)
flight_2 = self.flight_2.resolve(times)

with OpIntentValidator(
self,
self.control_uss_client,
self.dss,
"Validate flight 2 sharing",
self._intents_extent,
) as validator:
planning_time = Time(arrow.utcnow().datetime)
_, self.flight_2_id = plan_flight(
self,
"Control_uss plans flight 2",
self.control_uss_client,
flight_2,
)

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

self.begin_test_step(
"Precondition - check tested_uss has no subscription in flight 2 area"
"Check for notification to tested_uss due to subscription in flight 2 area"
)
tested_uss_notified = check_any_notification(
self,
self.control_uss,
planning_time,
)
# ToDo - Add the test step details
self.end_test_step()

times[TimeDuringTest.TimeOfEvaluation] = Time(arrow.utcnow().datetime)
Expand All @@ -170,24 +185,44 @@ def _tested_uss_plans_deconflicted_flight_near_existing_flight(
"Validate flight 1 sharing",
self._intents_extent,
) as validator:
_, self.flight_1_id = plan_flight(
planning_time = Time(arrow.utcnow().datetime)
plan_res, self.flight_1_id = plan_flight(
self,
"Tested_uss plans flight 1",
self.tested_uss_client,
flight_1,
)

validator.expect_shared(
flight_1,
)

self.begin_test_step("Validate flight2 GET interaction")
# ToDo - Add the test step details
self.end_test_step()
get_requested, already_notified = expect_get_requests_to_mock_uss(
Copy link
Member

Choose a reason for hiding this comment

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

Why even make this call when tested_uss_notified since it doesn't do anything when that indicator is True? It seems like this test step is simply not applicable when tested_uss received a notification, so therefore it should be skipped. It would be ok to stop the test scenario entirely (exactly as in the original precondition), but we could continue the scenario in the presence of a notification.

In other words, we don't expect_get_requests_to_mock_uss when tested_uss_notified.

Copy link
Contributor Author

@punamverma punamverma Dec 13, 2023

Choose a reason for hiding this comment

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

We have to do expect_get_requests_to_mock_uss, as some USS implementation might make a GET request even if they are notified, in that case we don't want to stop the test. We want to check GET requests, and we don't care if they make GET requests with/without being notified.

We stop the test, when 'GET request is not made' and 'the USS has been notified'.
But, we don't stop if 'GET request is made' even when 'the USS has been notified/ not notified'. Depends on USS implementation.
And fail the check if 'GET request is not made', and 'USS is not notified'

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 like this is what we want:

GET request made USS notified Desired outcome
No No Fail "Expect GET request" check
Yes No Pass "Expect GET request" check
No Yes Skip "Expect GET request" check since it's not applicable
Yes Yes Skip "Expect GET request" check since there is no way the USS could fail a requirement

To accomplish this, simply enclose the expect_get_requests_to_mock_uss call in an if not tested_uss_notified block and get rid of the evaluation of get_requested and already_notified just afterward.

Copy link
Contributor Author

@punamverma punamverma Dec 14, 2023

Choose a reason for hiding this comment

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

I agree with rows 1, 2 and 3. But, 4th should be Pass instead of Skip.

GET request made is what we want the tested_uss to do. In both rows 2 and 4 in the above table, GET request is made.

In the test, the tested_uss makes a GET request for flight 2 while planning flight1. And the data through GET request is invalid, hence we expect tested_uss to fail a plan. Depending on the implementation, a USS might GET flight2 even though it received a notification for it. They might not use notifications for planning, instead make a fresh GET request when planning. We should not Skip the test for them, as they did make a GET request, and we know that plan was failed from previous step.

So, in both the rows of the table, I think the desired outcome should be Pass.

GET request made USS notified Desired outcome
Yes No Pass "Expect GET request" check
Yes Yes Pass "Expect GET request" check because this USS did make a GET request for flight2 which was invalid.

Would that be incorrect?

Copy link
Member

Choose a reason for hiding this comment

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

If a USS already has the op intent details via a notification to their subscription, we would not expect them to perform a GET request. They are not strictly prohibited from making a GET request when they already have the details, but doing so would be unexpected and inefficient. The "Expect GET request" check is documented to say "[...] the only way to have verified this is by knowing all operational intent details, and (from previous checks of no notifications) the only way to know the operational intent details of flight is to have requested them via a GET details interaction." That check is not applicable and the documentation is not correct when the operational intent details are obtained a different way. It is therefore inappropriate to perform that check, and therefore it is inappropriate to mark it Passed.

GET request made is what we want the tested_uss to do.

Emphatically no; there is no requirement for a USS to make a GET request. The requirement (SCD0035) is that they get (and evaluate) the operational intent details before doing a particular thing. When they have no subscription, then we know they only way they can get the details is via a GET request, so in that situation we can conclude that they violated SCD0035 if they didn't make that GET request before doing the particular thing. When they do have a subscription, we can no longer conclude anything from the lack of a GET request which is why checking for a subscription used to be a precondition for performing this test step.

In the test, the tested_uss makes a GET request for flight 2 while planning flight1.

When they don't have a subscription, yes.

And the data through GET request is invalid, hence we expect tested_uss to fail a plan.

Not just the GET request, by the way -- the notification contains the same invalid data as well.

Depending on the implementation, a USS might GET flight2 even though it received a notification for it. They might not use notifications for planning, instead make a fresh GET request when planning.

Agreed (though this would be strange, inefficient, and eyebrow-raising; if they're not interested in the information they're getting through the subscription, then there is no reason for them to be loading the system with it)

We should not Skip the test for them, as they did make a GET request

No; the check says that the only way to have met SCD0035 in the situation we set up (where the check is performed) was to have performed a GET request. That is not true if they received a notification and also made a GET request (the situation to which the check pertains was never successfully set up).

Copy link
Member

Choose a reason for hiding this comment

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

As discussed separately at length, stopping the test scenario if we found that tested_uss has a subscription is not appropriate because the test scenario can continue (not correct that ScenarioCannotContinue) and the rest of the scenario includes valuable checks that we can successfully make even when tested_uss has a subscription. This includes, for instance, the only checks currently for SCD0085.

It is definitely appropriate to skip the checks in "Validate flight2 GET interaction test step" because they are not applicable when tested_uss has a subscription (as we do by placing it within an if block). However, the following step "Validate flight1 Notification sent to Control_uss test step" can be performed regardless of whether a subscription was detected. Likewise for the remaining two cleanup test steps in the test case. The second test case is independent of the first test case and can be performed regardless of subscription status in the first test case. Even if we were confident that we would need to skip "Validate flight 2 GET interaction test step" in the second test case (which we are not; some circumstances and implementations may result in being able to perform just one or the other), proceeding with the test scenario would still be valuable in order to perform checks like the ones in "Tested_uss attempts to plan flight 1, expect failure test step" and "Validate flight 1 not shared by tested_uss test step".

For these reasons, the else block should be removed.

My understanding of your hesitance to remove the else block is that you want the scenario to somehow not be successful if that "main" step/check cannot be performed, and raising ScenarioCannotContinueError is the means to accomplish that. We discussed that scenarios do not fail except for execution errors that indicate the test itself is broken; rather success is based on all checks passing when they are, in fact, made during the test, and ensuring that the test was capable of detecting noncompliance for each of the requirements that needed to be verified. Therefore, raising ScenarioCannotContinueError does not indicate that the scenario was not successful. We also discussed that we generally try to verify as many requirements as we can with a given simple test scenario, so there is no one "main" step/check without which the scenario does not have value. In this case specifically, checking SCD0085 is very valuable because this is the only scenario in which that requirement is checked. Therefore, we should not forego checking SCD0085 just because we are unable to check SCD0035 in this particular way.

Copy link
Contributor Author

@punamverma punamverma Dec 15, 2023

Choose a reason for hiding this comment

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

Ok, got it. I understand that ScenarioCannotContinueError is not the correct error to stop the scenario. And as you think we should not stop the test. I think I am good with removing the else block, but that brings a question to me how do I use the report to show that a check got skipped. And, that could probably be my lack of knowledge of reporting framework in interuss.

I know that in case when notifications are made, GET request check is going to be marked Not Tested. Is that the indication we need to use?

My hesitance, is because I am not clear how in the report do we indicate that GET request validation was skipped? You had mentioned that SCD0035 will be verified else where, hence this wouldn't show as not verified.
Then is there a way that I can use to indicate GET request validation could not be performed and was skipped? And that brought up the question if we can create an interuss requirement that can help us to show that the check got skipped. So that we are not dependent on SCD0035 which is being tested at other places.
Or is there any other way we could indicate skipping of a validation test?

Copy link
Member

Choose a reason for hiding this comment

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

The top-level goal of automated testing is verifying participant compliance to requirements. The way automated testing accomplishes this is to set up many situations where particular outcomes of observations can allow us to conclude that the participant did not meet one or more requirements. We can never positively declare that a participant meets all requirements; we can only say that we checked a bunch of situations and were unable to declare the participant non-compliant with any of a set of requirements with which we could have potentially declared them non-compliant. With that in mind,

how in the report do we indicate that GET request validation was skipped

Skipped checks are indicated as Not tested in the tested requirements artifact. An example tested requirements artifact that is generated with every merge to main may be found here. However, skipping a check does not have any impact on whether we can verify compliance to the associated requirement unless that check is the only check verifying compliance to the requirement. This is because of the above: verification of compliance is based on 1) no failures and 2) capability to detect noncompliance.

Then is there a way that I can use to indicate GET request validation could not be performed and was skipped?

It shouldn't be important to know this. If a USS is required to perform actions that will allow us to set up the check, then we can indicate failure if the USS does not perform those actions, and therefore we will either perform the check or report a failure. If a USS is not required to perform actions that will allow us to set up the check, then we can perform the check if possible, but if we can't perform the check then we can't report any failures because the USS was not required to do the things that would enable us to perform the check. We are in the latter situation here. The problem is that you want to claim that there was a failure in that latter situation when in fact there was not. The fact that GET request validation could not be performed and was skipped is not relevant to whether the USS under test is fully compliant with all ASTM F3548-21 requirements.

InterUSS sometimes imposes additional requirements to make it possible to perform effective automated testing -- for instance, implementation of the flight_planning interface is not prescribed by ASTM or any other standards or regulatory body, rather it is something InterUSS requires a USS to do in order to be tested by uss_qualifier for ASTM F3548-21. We try hard to keep these additional requirements to a minimum, and we try extremely hard to make it so these requirements do not preclude any reasonable system that is compliant with the requirements we want to test from passing the test suite after some additional development wholly outside the system under test. We are open to potential additional requirements that follow these criteria, but I am not sure what requirement we could reasonably add here. "GET request validation must be performed" is not a requirement a USS can use to design their system. "A USS may not proactively make any subscriptions before a concrete flight plan is proposed and subscriptions must be removed after all flights in the area are finished" is a more reasonable requirement, but F3548-21 specifically allows this design freedom and InterUSS would not want to take away this design freedom.

NASA can make whatever requirements it wants if there is a NASA program under which USSs would be tested -- so, for instance, NASA could specify "A USS may not proactively [...]". However, that requirement would be above and beyond ASTM F3548-21 and therefore would be checked in a separate NASA program test suite and not in the ASTM F3548-21 test suite. NASA could even add a "GET request validation must be performed" requirement for the NASA test program, but that I would expect USSs to challenge the value of that requirement because it is not apparent what outcome could not be accomplished without this requirement. ASTM, through its standards development process, has come to the conclusion that a USS needs to verify an operational intent does not conflict with an equal priority operational intent under certain circumstances (SCD0035). This is a performance-based requirement that is purposefully agnostic of the means by which that requirement is accomplished. Making a GET request is one path to compliance with this requirement, but it is not the only one. If NASA requires that USSs must take the GET request path specifically, that limits design freedom that F3548 allows, and it is unclear what objective could not be met if an alternate path were taken (yet the F3548 performance-based requirement were still met).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem is that you want to claim that there was a failure in that latter situation when in fact there was not. The fact that GET request validation could not be performed and was skipped is not relevant to whether the USS under test is fully compliant with all ASTM F3548-21 requirements.

No, I am not wanting to show it as a failure. I am wanting to show it as a skipped test that we could not verify on that uss, because of certain conditions that occurred for this uss - in this case notifications due to subscription.

We are open to potential additional requirements that follow these criteria, but I am not sure what requirement we could reasonably add here. "GET request validation must be performed" is not a requirement a USS can use to design their system. "A USS may not proactively make any subscriptions before a concrete flight plan is proposed and subscriptions must be removed after all flights in the area are finished" is a more reasonable requirement, but F3548-21 specifically allows this design freedom and InterUSS would not want to take away this design freedom.

No, I don't want "GET request validation must be performed" instead it is "If a USS makes GET requests, they must validate the data received". And, if they don't we want to be able to know that it got skipped because they never made a GET request because of notifications due to subscriptions.

I am not sure how feasible would it be to ask that for the requirement "A USS may not proactively make any subscriptions before a concrete flight plan is proposed and subscriptions must be removed after all flights in the area are finished". But, if it can then that would definitely force a USS to make a GET request.
I am not sure if we want to that extent, but we can discuss that in our meeting.

NASA can make whatever requirements it wants if there is a NASA program under which USSs would be tested -- so, for instance, NASA could specify "A USS may not proactively [...]". However, that requirement would be above and beyond ASTM F3548-21 and therefore would be checked in a separate NASA program test suite and not in the ASTM F3548-21 test suite. NASA could even add a "GET request validation must be performed" requirement for the NASA test program, but that I would expect USSs to challenge the value of that requirement because it is not apparent what outcome could not be accomplished without this requirement. ASTM, through its standards development process, has come to the conclusion that a USS needs to verify an operational intent does not conflict with an equal priority operational intent under certain circumstances (SCD0035). This is a performance-based requirement that is purposefully agnostic of the means by which that requirement is accomplished. Making a GET request is one path to compliance with this requirement, but it is not the only one. If NASA requires that USSs must take the GET request path specifically, that limits design freedom that F3548 allows, and it is unclear what objective could not be met if an alternate path were taken (yet the F3548 performance-based requirement were still met).

I don't think there is any such NASA requirement at the moment, we can check on that just in case, during our meeting.
But through the report we would want to know that if GET request validation could not be done for a USS because they had notifications due to subscriptions. So, the USS is not non-compliant but there are some tests we could not do on a USS.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Made changes as discussed. Removed else block.

self,
self.control_uss,
planning_time,
self.control_uss.base_url,
flight_2_oi_ref.id,
self.tested_uss_client.participant_id,
tested_uss_notified,
"Validate flight2 GET interaction",
)

self.begin_test_step("Validate flight1 Notification sent to Control_uss")
# ToDo - Add the test step details
self.end_test_step()
if get_requested == False and already_notified == True:
BenjaminPelletier marked this conversation as resolved.
Show resolved Hide resolved
msg = (
f"GET request was not made by tested_uss, as it was notified of flight2, due to an existing subscription. "
f"See documentation of test step - Check for notification to tested_uss due to subscription in flight 2 area"
)
raise ScenarioCannotContinueError(msg)

expect_interuss_post_interactions(
self,
self.control_uss,
planning_time,
self.control_uss.base_url,
self.tested_uss_client.participant_id,
plan_res.queries[0].request.timestamp,
"Validate flight1 Notification sent to Control_uss",
)

delete_flight(
self, "Delete tested_uss flight", self.tested_uss_client, self.flight_1_id
Expand All @@ -202,58 +237,89 @@ def _tested_uss_unable_to_plan_flight_near_invalid_shared_existing_flight(
times[TimeDuringTest.TimeOfEvaluation] = Time(arrow.utcnow().datetime)
flight_info = self.flight_2.resolve(times)

modify_field1 = "state"
modify_field2 = "priority"
# Modifying the request with invalid data
behavior = MockUssFlightBehavior(
modify_sharing_methods=["GET", "POST"],
modify_fields={
"reference": {"state": "Flying"},
"details": {"priority": -1},
"reference": {modify_field1: "Flying"},
"details": {modify_field2: 1.2},
},
)

additional_fields = {"behavior": behavior}

_, self.flight_2_id = plan_flight(
with OpIntentValidator(
self,
"Control_uss plans flight 2, sharing invalid operational intent data",
self.control_uss_client,
flight_info,
additional_fields,
)
self.dss,
"Validate flight 2 shared operational intent with invalid data",
self._intents_extent,
) as validator:
planning_time = Time(arrow.utcnow().datetime)
_, 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_specified_data(
flight_info,
validation_failure_type=OpIntentValidationFailureType.DataFormat,
invalid_fields=[modify_field1, modify_field2],
)

self.begin_test_step(
"Validate flight 2 shared operational intent with invalid data"
"Check for notification to tested_uss due to subscription in flight 2 area"
)
# ToDo - Add the test step details
self.end_test_step()

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

times[TimeDuringTest.TimeOfEvaluation] = Time(arrow.utcnow().datetime)
flight_1 = self.flight_1.resolve(times)

_, self.flight_1_id = plan_flight_intent_expect_failed(
with OpIntentValidator(
self,
"Tested_uss attempts to plan flight 1, expect failure",
self.tested_uss_client,
flight_1,
)
self.dss,
"Validate flight 1 not shared by tested_uss",
self._intents_extent,
) as validator:
planning_time = Time(arrow.utcnow().datetime)
_, self.flight_1_id = plan_flight_intent_expect_failed(
self,
"Tested_uss attempts to plan flight 1, expect failure",
self.tested_uss_client,
flight_1,
)
validator.expect_not_shared()

self.begin_test_step("Validate flight 1 not shared by tested_uss")
# ToDo - Add the test step details
self.end_test_step()
get_requested, already_notified = expect_get_requests_to_mock_uss(
self,
self.control_uss,
planning_time,
self.control_uss.base_url,
flight_2_oi_ref.id,
self.tested_uss_client.participant_id,
tested_uss_notified,
"Validate flight 2 GET interaction",
)

self.begin_test_step("Validate flight 2 GET interaction")
# ToDo - Add the test step details
self.end_test_step()
if get_requested == False and already_notified == True:
msg = f"GET request was not made by tested_uss, as it was notified of flight2, due to an exisitng subscription."
raise ScenarioCannotContinueError(msg)

self.begin_test_step("Validate flight 1 Notification not sent to Control_uss")
# ToDo - Add the test step details
self.end_test_step()
expect_no_interuss_post_interactions(
self,
self.control_uss,
planning_time,
self.tested_uss_client.participant_id,
"Validate flight 1 Notification not sent to Control_uss",
)

delete_flight(
self, "Delete Control_uss flight", self.control_uss_client, self.flight_2_id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
MaxTimeToWaitForSubscriptionNotificationSeconds = 7
BenjaminPelletier marked this conversation as resolved.
Show resolved Hide resolved
"""
This constant is used for waiting to check notifications were sent to mock_uss for an entity created
by another USS, due to subscription in that area.
The details of usage of this constant are in ./validate_notification_operational_intent.md
and ./validate_no_notification_operational_intent.md
"""
Loading
Loading