Skip to content

Commit

Permalink
[uss_qualifier] oir_simple: check oir can be created without sub and …
Browse files Browse the repository at this point in the history
…attached to explicit sub
  • Loading branch information
Shastick committed Oct 15, 2024
1 parent 3a10cf3 commit 6c9828a
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ Check query succeeds

If the OIR returned by the DSS under test is not attached to the expected subscription,
it is in violation of **[astm.f3548.v21.DSS0005,1](../../../../../../requirements/astm/f3548/v21.md)**

## [Get referenced Subscription](../sub/crud/read_query.md)

Attempt to fetch the subscription referenced by the OIR in order to confirm that it does not exist.

This is only used in circumstances where the subscription is expected to not exist and the DSS implementation
is not using the _null_ subscription ID with value `00000000-0000-4000-8000-000000000000`.
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,65 @@ Verifies the behavior of a DSS for simple interactions pertaining to operational

This step ensures that no entities with the known test IDs exists in the DSS.

## OIR in ACCEPTED state can be created without subscription test case

Checks that a DSS allows an OIR to be created in the accepted state without any subscription.

### [Create an operational intent reference test step](./fragments/oir/crud/create_query.md)

This step verifies that an OIR can be created in the ACCEPTED state without providing any subscription information (implicit or explicit) in the request.

### [OIR is not attached to any subscription test step](./fragments/oir/oir_has_expected_subscription.md)

This step verifies that the OIR is not attached to any subscription.

#### 🛑 Referenced subscription does not exist check

If the placeholder subscription contained in the OIR returned to the qualifier by the DSS references an existing subscription,
then the DSS under test is in violation of **[astm.f3548.v21.DSS0005,1](../../../../requirements/astm/f3548/v21.md)**, as the creation request
did not specify any subscription.

## Validate explicit subscription being attached to OIR without subscription test case

Ensures that an explicit subscription can be attached to an OIR without subscription attached, and that the subscription is required to properly cover the OIR.

### [Create a subscription test step](./fragments/sub/crud/create_query.md)

Create an explicit subscription to be used in this scenario.
Create an explicit subscription to be used in this test cases.

### Attempt to attach insufficient subscription to OIR test step

This step verifies that the DSS refuses the request to attach an insufficient subscription to an OIR that currently has no subscription.

#### 🛑 Request to attach insufficient subscription to OIR fails check

If the DSS under test allows the qualifier to attach an insufficient explicit subscription to a subscription-free OIR,
it is in violation of **[astm.f3548.v21.DSS0005,1](../../../../requirements/astm/f3548/v21.md)**

### [OIR is not attached to any subscription test step](./fragments/oir/oir_has_expected_subscription.md)

This step verifies that the OIR is not attached to any subscription.

### [Attach explicit subscription to OIR test step](./fragments/oir/crud/update_query.md)

This step verifies that an explicit subscription covering the OIR can be attached to an OIR that currently has no subscription.

### [OIR is attached to expected subscription test step](./fragments/oir/oir_has_expected_subscription.md)

This step verifies that the OIR is attached to the subscription provided upon creation.

## Validate explicit subscription on OIR creation test case

Ensures that the explicit subscription provided upon creation of an OIR is properly validated and attached to the OIR.

### [Ensure clean workspace test step](./clean_workspace.md)

This step ensures that no entities with the known test IDs exists in the DSS.

### [Create a subscription test step](./fragments/sub/crud/create_query.md)

Create an explicit subscription to be used in this and the following test cases.

### Provide subscription not covering extent of OIR being created test step

This step verifies that an OIR cannot be created when an explicit subscription that does not cover the extent of the OIR is specified.
Expand Down
126 changes: 111 additions & 15 deletions monitoring/uss_qualifier/scenarios/astm/utm/dss/op_intent_ref_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@
)
from monitoring.uss_qualifier.suites.suite import ExecutionContext

# The official DSS implementation will set an OIR's subscription ID to 00000000-0000-4000-8000-000000000000
# when the OIR is not attached to any subscription, as the OpenAPI spec does not allow the value to be empty.
# Other implementations may use a different value. One way to check that an OIR is not attached to any subscription
# is to attempt to retrieve the subscription reportedly attached to it: if a 404 is returned then we may assume
# no subscription is attached.
# Note that this is only allowed for OIRs in the ACCEPTED state.
NULL_SUBSCRIPTION_ID = "00000000-0000-4000-8000-000000000000"


class OIRSimple(TestScenario):
"""
Expand Down Expand Up @@ -103,10 +111,37 @@ def __init__(
def run(self, context: ExecutionContext):
self.begin_test_scenario(context)
self.begin_test_case("Setup")
self._setup_case(create_explicit_sub=True)
self._setup_case()
self.end_test_case()

self.begin_test_case(
"OIR in ACCEPTED state can be created without subscription"
)
self._step_create_oir(
oir_params=self._planning_area.get_new_operational_intent_ref_params(
key=[],
state=OperationalIntentState.Accepted,
uss_base_url=self._planning_area.get_base_url(),
time_start=datetime.now() - timedelta(seconds=10),
time_end=datetime.now() + timedelta(minutes=20),
subscription_id=None,
implicit_sub_base_url=None,
),
)
self._step_oir_has_correct_subscription(expected_sub_id=None)
self.end_test_case()

self.begin_test_case(
"Validate explicit subscription being attached to OIR without subscription"
)
self._step_update_oir_with_insufficient_explicit_sub(is_replacement=False)
self._step_oir_has_correct_subscription(expected_sub_id=None)
self._step_update_oir_with_sufficient_explicit_sub(is_replacement=False)
self._step_oir_has_correct_subscription(expected_sub_id=self._extra_sub_id)
self.end_test_case()

self.begin_test_case("Validate explicit subscription on OIR creation")
self._setup_case(create_explicit_sub=True)
self._step_create_oir_insufficient_subscription()
self._step_create_oir(
oir_params=self._planning_area.get_new_operational_intent_ref_params(
Expand All @@ -124,9 +159,9 @@ def run(self, context: ExecutionContext):
self.begin_test_case(
"Validate explicit subscription upon subscription replacement"
)
self._step_update_oir_with_insufficient_explicit_sub()
self._step_update_oir_with_insufficient_explicit_sub(is_replacement=True)
self._step_oir_has_correct_subscription(expected_sub_id=self._sub_id)
self._step_update_oir_with_sufficient_explicit_sub()
self._step_update_oir_with_sufficient_explicit_sub(is_replacement=True)
self._step_oir_has_correct_subscription(expected_sub_id=self._extra_sub_id)
self.end_test_case()

Expand Down Expand Up @@ -177,13 +212,18 @@ def _step_create_oir(self, oir_params: PutOperationalIntentReferenceParameters):
self._pid,
) as check:
try:
no_implicit_sub = (
"new_subscription" not in oir_params
or "uss_base_url" not in oir_params.new_subscription
)
new_oir, subs, query = self._dss.put_op_intent(
extents=oir_params.extents,
key=oir_params.key,
state=oir_params.state,
base_url=oir_params.uss_base_url,
oi_id=self._oir_id,
subscription_id=sub_id,
force_no_implicit_subscription=no_implicit_sub,
)
self.record_query(query)
self._current_oir = new_oir
Expand Down Expand Up @@ -243,7 +283,7 @@ def _step_create_oir_insufficient_subscription(self):

self.end_test_step()

def _step_update_oir_with_insufficient_explicit_sub(self):
def _step_update_oir_with_insufficient_explicit_sub(self, is_replacement: bool):
# Create another subscription that is a few seconds short of covering the OIR:
oir_duration = (
self._current_oir.time_end.value.datetime
Expand All @@ -268,12 +308,19 @@ def _step_update_oir_with_insufficient_explicit_sub(self):
time_end=self._current_oir.time_end.value.datetime,
subscription_id=self._extra_sub_id,
)

self.begin_test_step(
step_name = (
"Attempt to replace OIR's existing explicit subscription with an insufficient one"
if is_replacement
else "Attempt to attach insufficient subscription to OIR"
)
self.begin_test_step(step_name)
check_name = (
"Request to mutate OIR while providing an incorrect subscription fails"
if is_replacement
else "Request to attach insufficient subscription to OIR fails"
)
with self.check(
"Request to mutate OIR while providing an incorrect subscription fails",
check_name,
self._pid,
) as check:
try:
Expand All @@ -289,7 +336,7 @@ def _step_update_oir_with_insufficient_explicit_sub(self):
self.record_query(q)
# We don't expect to reach this point:
check.record_failed(
summary="OIR mutation with too short subscription was not expected to succeed",
summary="Request for OIR with too short subscription was not expected to succeed",
details=f"Was expecting an HTTP 400 response because of an insufficient subscription, but got {q.status_code} instead",
query_timestamps=[q.request.timestamp],
)
Expand All @@ -299,14 +346,19 @@ def _step_update_oir_with_insufficient_explicit_sub(self):
pass
else:
check.record_failed(
summary="OIR mutation with too short subscription failed for unexpected reason",
summary="Request for OIR with too short subscription failed for unexpected reason",
details=f"Was expecting an HTTP 400 response because of an insufficient subscription, but got {qe.cause_status_code} instead. {qe.msg}",
query_timestamps=qe.query_timestamps,
)
self.end_test_step()

def _step_update_oir_with_sufficient_explicit_sub(self):
self.begin_test_step("Replace the OIR's explicit subscription")
def _step_update_oir_with_sufficient_explicit_sub(self, is_replacement: bool):
step_name = (
"Replace the OIR's explicit subscription"
if is_replacement
else "Attach explicit subscription to OIR"
)
self.begin_test_step(step_name)
oir_update_params = self._planning_area.get_new_operational_intent_ref_params(
key=[],
state=OperationalIntentState.Accepted,
Expand Down Expand Up @@ -340,8 +392,15 @@ def _step_update_oir_with_sufficient_explicit_sub(self):
)
self.end_test_step()

def _step_oir_has_correct_subscription(self, expected_sub_id: SubscriptionID):
self.begin_test_step("OIR is attached to expected subscription")
def _step_oir_has_correct_subscription(
self, expected_sub_id: Optional[SubscriptionID]
):
step_check_name = (
"OIR is attached to expected subscription"
if expected_sub_id
else "OIR is not attached to any subscription"
)
self.begin_test_step(step_check_name)
with self.check("Get operational intent reference by ID", self._pid) as check:
try:
oir, q = self._dss.get_op_intent_reference(self._oir_id)
Expand All @@ -354,11 +413,48 @@ def _step_oir_has_correct_subscription(self, expected_sub_id: SubscriptionID):
query_timestamps=qe.query_timestamps,
)

with self.check("OIR is attached to expected subscription") as check:
if oir.subscription_id != expected_sub_id:
sub_is_as_expected = False
referenced_sub_was_found_when_non_expected = False
if expected_sub_id is None:
# The official DSS implementation will set the subscription ID to 00000000-0000-4000-8000-000000000000 when the OIR is not attached to any subscription.
# Other implementations may use a different value, as the OpenAPI spec does not allow the value to be empty
# We may at some point decide to tolerate accepting empty returned values here,
# but in the meantime we simply attempt to obtain the subscription and check that it does not exist
if oir.subscription_id == NULL_SUBSCRIPTION_ID:
# Sub ID explicitly set to the value representing the null subscription: all good
sub_is_as_expected = True
elif oir.subscription_id is None:
# Sub ID not set at all: not strictly compliant with the spec, but acceptable in this context
sub_is_as_expected = True
else:
# If the subscription ID is defined and not set to the known 'null' value, we assume that the DSS used another
# placeholder for the non-existing subscription, and we check that it does not exist.
with self.check("Get referenced Subscription") as check:
sub = self._dss.get_subscription(oir.subscription_id)
self.record_query(sub)
if sub.status_code not in [200, 404]:
check.record_failed(
summary="Failed to try to obtain the subscription referenced by the OIR",
details=f"Failed in an unexpected way while querying subscription with ID {oir.subscription_id}: expected a 404 or 200, but got {sub.status_code}",
query_timestamps=[sub.request.timestamp],
)
if sub.status_code == 200:
referenced_sub_was_found_when_non_expected = True
else:
sub_is_as_expected = oir.subscription_id == expected_sub_id

with self.check("OIR is attached to expected subscription", self._pid) as check:
if referenced_sub_was_found_when_non_expected:
check.record_failed(
summary="OIR is attached to a subscription although it should not be",
details=f"Expected OIR to not be attached to any subscription, but the referenced subscription {oir.subscription_id} does exist.",
query_timestamps=[sub.request.timestamp],
)
if not sub_is_as_expected:
check.record_failed(
summary="OIR is not attached to the correct subscription",
details=f"Expected OIR to be attached to subscription {expected_sub_id}, but it is attached to {oir.subscription_id}",
query_timestamps=[q.request.timestamp],
)
self.end_test_step()

Expand Down

0 comments on commit 6c9828a

Please sign in to comment.