Skip to content

Commit d9641fc

Browse files
committed
[uss_qualifier] uss availability status: version conflict
get old version before updating availability fix test check mismatch fix doc OVN/version naming record all queries factorize fragments
1 parent e57ce24 commit d9641fc

File tree

11 files changed

+270
-125
lines changed

11 files changed

+270
-125
lines changed

monitoring/uss_qualifier/scenarios/astm/utm/dss/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@
2020
)
2121
from .subscription_simple import SubscriptionSimple as SubscriptionSimple
2222
from .subscription_validation import SubscriptionValidation as SubscriptionValidation
23+
from .uss_availability_simple import UssAvailabilitySimple as UssAvailabilitySimple

monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/availability/read.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# USS Availability Read test step fragment
22

3-
This fragment contains the steps for the USS Availability synchronization scenario
3+
This fragment contains the steps for the USS Availability scenario
44
where we confirm that a USS availability can be correctly read from a DSS instance
55

66
## 🛑 USS Availability can be requested check

monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/availability/sync.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# USS Availability Sync test step fragment
22

3-
## 🛑USS Availability is consistent across every DSS instance check
3+
## 🛑 USS Availability is consistent across every DSS instance check
44

55
If the reported availability for a USS is not consistent, across a set of DSS instances, with the value that was previously read or set on an arbitrary DSS instance,
66
either the DSS through which the value was set or the one through which the values was retrieved is failing to meet at least one of these requirements:
@@ -11,7 +11,7 @@ either the DSS through which the value was set or the one through which the valu
1111

1212
As a consequence, the DSS also fails to meet **[astm.f3548.v21.DSS0210,A2-7-2,6](../../../../../../requirements/astm/f3548/v21.md)** and **[astm.f3548.v21.DSS0020](../../../../../../requirements/astm/f3548/v21.md)**.
1313

14-
## 🛑USS Availability version is consistent across every DSS instance check
14+
## 🛑 USS Availability version is consistent across every DSS instance check
1515

1616
If the reported availability version for a USS is not consistent, across a set of DSS instances, with the value that was previously read or set on an arbitrary DSS instance,
1717
either the DSS through which the value was set or the one through which the values was retrieved is failing to meet at least one of these requirements:
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# USS Availability Read test step fragment
1+
# USS Availability Update test step fragment
22

3-
This fragment contains the steps for the USS Availability synchronization scenario
3+
This fragment contains the steps for the USS Availability scenario
44
where we confirm that a USS availability can be correctly read from a DSS instance
55

6-
## 🛑USS Availability can be updated check
6+
## 🛑 USS Availability can be updated check
77

88
If, when presented with a valid query to update the availability state of a USS, a DSS
99
responds with anything else than a 200 OK response, it is in violation of the OpenAPI specification referenced by **[astm.f3548.v21.DSS0100,1](../../../../../../requirements/astm/f3548/v21.md)**.

monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/uss_availability_synchronization.py

Lines changed: 38 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
DSSInstancesResource,
99
)
1010
from monitoring.uss_qualifier.resources.communications import ClientIdentityResource
11+
from monitoring.uss_qualifier.scenarios.astm.utm.test_steps import (
12+
get_uss_availability,
13+
set_uss_availability,
14+
)
1115
from monitoring.uss_qualifier.scenarios.scenario import TestScenario
1216
from monitoring.uss_qualifier.suites.suite import ExecutionContext
1317

@@ -46,7 +50,7 @@ def __init__(
4650
"""
4751
super().__init__()
4852
scopes_primary = {
49-
Scope.AvailabilityArbitration: "Set and read USS availability states"
53+
Scope.AvailabilityArbitration: "set and read USS availability states"
5054
}
5155
scopes_read = {Scope.StrategicCoordination: "read USS availability states"}
5256

@@ -145,84 +149,45 @@ def _step_unknown_uss_reported_as_unknown(self):
145149
)
146150

147151
def _step_update_to_unknown(self):
148-
with self.check(
149-
"USS Availability can be updated", self._dss.participant_id
150-
) as check:
151-
try:
152-
self._current_version, q = self._dss.set_uss_availability(
153-
self._uss_id, UssAvailabilityState.Unknown, self._current_version
154-
)
155-
self.record_query(q)
156-
except QueryError as qe:
157-
self.record_queries(qe.queries)
158-
check.record_failed(
159-
summary="Failed to set USS availability to Unknown",
160-
details=qe.msg,
161-
query_timestamps=qe.query_timestamps,
162-
)
152+
self._current_version = set_uss_availability(
153+
self,
154+
self._dss,
155+
self._uss_id,
156+
UssAvailabilityState.Unknown,
157+
self._current_version,
158+
)
163159

164160
def _step_update_to_down(self):
165-
with self.check(
166-
"USS Availability can be updated", self._dss.participant_id
167-
) as check:
168-
try:
169-
self._current_version, q = self._dss.set_uss_availability(
170-
self._uss_id, UssAvailabilityState.Down, self._current_version
171-
)
172-
self.record_query(q)
173-
except QueryError as qe:
174-
self.record_queries(qe.queries)
175-
check.record_failed(
176-
summary="Failed to set USS availability to Down",
177-
details=qe.msg,
178-
query_timestamps=qe.query_timestamps,
179-
)
161+
self._current_version = set_uss_availability(
162+
self,
163+
self._dss,
164+
self._uss_id,
165+
UssAvailabilityState.Down,
166+
self._current_version,
167+
)
180168

181169
def _step_update_to_normal(self):
182-
with self.check(
183-
"USS Availability can be updated", self._dss.participant_id
184-
) as check:
185-
try:
186-
self._current_version, q = self._dss.set_uss_availability(
187-
self._uss_id, UssAvailabilityState.Normal, self._current_version
188-
)
189-
self.record_query(q)
190-
except QueryError as qe:
191-
self.record_queries(qe.queries)
192-
check.record_failed(
193-
summary="Failed to set USS availability to Normal",
194-
details=qe.msg,
195-
query_timestamps=qe.query_timestamps,
196-
)
170+
self._current_version = set_uss_availability(
171+
self,
172+
self._dss,
173+
self._uss_id,
174+
UssAvailabilityState.Normal,
175+
self._current_version,
176+
)
197177

198178
def _ensure_test_uss_availability_unknown(self, check_consistency: bool = True):
199179
"""
200180
Ensure that the availability of the USS being used for the test is set to 'Unknown',
201181
the default state for USS availability when nothing else is known.
202182
We want to both start and end this scenario with this state.
203183
"""
204-
205-
with self.check(
206-
"USS Availability can be requested", self._dss.participant_id
207-
) as check:
208-
try:
209-
availability, q = self._dss.get_uss_availability(
210-
self._uss_id, Scope.AvailabilityArbitration
211-
)
212-
self.record_query(q)
213-
except QueryError as qe:
214-
self.record_queries(qe.queries)
215-
check.record_failed(
216-
summary="Failed to get USS availability",
217-
details=qe.msg,
218-
query_timestamps=qe.query_timestamps,
219-
)
220-
return
221-
222-
self._current_version = availability.version
184+
availability, version = get_uss_availability(
185+
self, self._dss, self._uss_id, Scope.AvailabilityArbitration
186+
)
187+
self._current_version = version
223188

224189
# If the state is not currently unknown, we set it to unknown
225-
if availability.status.availability != UssAvailabilityState.Unknown:
190+
if availability != UssAvailabilityState.Unknown:
226191
with self.check("USS Availability can be set to Unknown") as check:
227192
try:
228193
self._current_version, q = self._dss.set_uss_availability(
@@ -254,40 +219,27 @@ def _query_and_expect_on_secondary(
254219
expected_availability: UssAvailabilityState,
255220
expected_version: str,
256221
):
257-
with self.check(
258-
"USS Availability can be requested", dss.participant_id
259-
) as check:
260-
try:
261-
availability, q = dss.get_uss_availability(
262-
uss_id, Scope.StrategicCoordination
263-
)
264-
self.record_query(q)
265-
except QueryError as qe:
266-
self.record_queries(qe.queries)
267-
check.record_failed(
268-
summary="Failed to get USS availability",
269-
details=qe.msg,
270-
query_timestamps=qe.query_timestamps,
271-
)
272-
return
222+
availability, version = get_uss_availability(
223+
self, dss, uss_id, Scope.StrategicCoordination
224+
)
273225

274226
with self.check(
275227
"USS Availability is consistent across every DSS instance", participants
276228
) as check:
277-
if availability.status.availability != expected_availability:
229+
if availability != expected_availability:
278230
check.record_failed(
279231
summary="USS availability not as expected on secondary DSS",
280-
details=f"Expected {expected_availability}, got {availability.status.availability}",
232+
details=f"Expected {expected_availability}, got {availability}",
281233
)
282234

283235
with self.check(
284236
"USS Availability version is consistent across every DSS instance",
285237
participants,
286238
) as check:
287-
if availability.version != expected_version:
239+
if version != expected_version:
288240
check.record_failed(
289241
summary="USS availability version not as expected on secondary DSS",
290-
details=f"Expected {expected_version}, got {availability.version}",
242+
details=f"Expected {expected_version}, got {version}",
291243
)
292244

293245
def _query_and_expect_on_secondaries(
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# ASTM Availability DSS: USS Availability Simple test scenario
2+
3+
## Overview
4+
5+
Verifies the behavior of a DSS for simple interactions pertaining to USS availability status.
6+
7+
## Resources
8+
9+
### dss
10+
11+
[`DSSInstanceResource`](../../../../resources/astm/f3548/v21/dss.py) the DSS instance through which entities are created, modified and deleted.
12+
13+
### client_identity
14+
15+
[`ClientIdentityResource`](../../../../resources/communications/client_identity.py) the client identity with the `utm.availability_arbitration` scope that will be used to report the availability status.
16+
17+
## Setup test case
18+
19+
### [Declare USS as available at DSS test step](../set_uss_available.md)
20+
21+
## Update requires correct version test case
22+
23+
Test DSS behavior when update requests are not providing the required version.
24+
25+
### Attempt update with missing version test step
26+
27+
This step verifies that an existing USS availability status cannot be mutated with a missing version.
28+
29+
#### 🛑 Request to update USS availability status with empty version fails check
30+
31+
If the DSS under test allows the qualifier to update the USS availability status with a request that provided an empty version, it is in violation of **[astm.f3548.v21.DSS0100,1](../../../../requirements/astm/f3548/v21.md)**
32+
33+
### Attempt update with incorrect version test step
34+
35+
This step verifies that an existing OIR cannot be mutated with an incorrect version.
36+
37+
#### 🛑 Request to update USS availability status with incorrect version fails check
38+
39+
If the DSS under test allows the qualifier to update the USS availability status with a request that provided an incorrect version,
40+
it is in violation of **[astm.f3548.v21.DSS0005,1](../../../../requirements/astm/f3548/v21.md)**
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
from uas_standards.astm.f3548.v21.api import UssAvailabilityState
2+
from uas_standards.astm.f3548.v21.constants import Scope
3+
4+
from monitoring.monitorlib.fetch import QueryError
5+
from monitoring.uss_qualifier.resources.astm.f3548.v21.dss import (
6+
DSSInstance,
7+
DSSInstanceResource,
8+
)
9+
from monitoring.uss_qualifier.resources.communications import ClientIdentityResource
10+
from monitoring.uss_qualifier.scenarios.astm.utm.test_steps import set_uss_available
11+
from monitoring.uss_qualifier.scenarios.scenario import TestScenario
12+
from monitoring.uss_qualifier.suites.suite import ExecutionContext
13+
14+
15+
class UssAvailabilitySimple(TestScenario):
16+
"""
17+
A scenario that verifies that USS availability status cannot be updated with the incorrect version.
18+
"""
19+
20+
_dss: DSSInstance
21+
22+
_uss_id: str
23+
24+
def __init__(
25+
self,
26+
dss: DSSInstanceResource,
27+
client_identity: ClientIdentityResource,
28+
):
29+
"""
30+
Args:
31+
dss: dss to test
32+
id_generator: will let us generate specific identifiers
33+
client_identity: tells us the identity we should expect as an entity's manager
34+
"""
35+
super().__init__()
36+
scopes: dict[str, str] = {
37+
Scope.AvailabilityArbitration: "read and set availability for a USS"
38+
}
39+
40+
self._dss = dss.get_instance(scopes)
41+
self._pid = [self._dss.participant_id]
42+
43+
self._uss_id = client_identity.subject()
44+
45+
def run(self, context: ExecutionContext):
46+
self._current_version = None
47+
48+
self.begin_test_scenario(context)
49+
50+
self.begin_test_case("Setup")
51+
self._step_declare_uss_available()
52+
self.end_test_case()
53+
54+
self.begin_test_case("Update requires correct version")
55+
self._step_attempt_update_missing_version()
56+
self._step_attempt_update_incorrect_version()
57+
self.end_test_case()
58+
59+
def _step_declare_uss_available(self):
60+
self.begin_test_step("Declare USS as available at DSS")
61+
self._current_version = set_uss_available(
62+
self,
63+
self._dss,
64+
self._uss_id,
65+
)
66+
self.end_test_step()
67+
68+
def _step_attempt_update_missing_version(self):
69+
self.begin_test_step("Attempt update with missing version")
70+
with self.check(
71+
"Request to update USS availability status with empty version fails",
72+
self._pid,
73+
) as check:
74+
try:
75+
_, q = self._dss.set_uss_availability(
76+
self._uss_id,
77+
UssAvailabilityState.Down,
78+
"",
79+
)
80+
self.record_query(q)
81+
# We don't expect the reach this point:
82+
check.record_failed(
83+
summary="Set USS availability with missing version was not expected to succeed",
84+
details=f"Was expecting an HTTP 409 response because of an missing version, but got {q.status_code} instead",
85+
query_timestamps=[q.request.timestamp],
86+
)
87+
except QueryError as qe:
88+
self.record_queries(qe.queries)
89+
if qe.cause_status_code == 409:
90+
# The spec explicitly requests a 409 response code for incorrect OVNs.
91+
pass
92+
else:
93+
check.record_failed(
94+
summary="Set USS availability with missing version failed for unexpected reason",
95+
details=f"Was expecting an HTTP 409 response because of an missing version, but got {qe.cause_status_code} instead",
96+
query_timestamps=qe.query_timestamps,
97+
)
98+
self.end_test_step()
99+
100+
def _step_attempt_update_incorrect_version(self):
101+
self.begin_test_step("Attempt update with incorrect version")
102+
with self.check(
103+
"Request to update USS availability status with incorrect version fails",
104+
self._pid,
105+
) as check:
106+
try:
107+
_, q = self._dss.set_uss_availability(
108+
self._uss_id,
109+
UssAvailabilityState.Down,
110+
"ThisIsAnIncorrectVersion",
111+
)
112+
self.record_query(q)
113+
# We don't expect the reach this point:
114+
check.record_failed(
115+
summary="Set USS availability with incorrect version was not expected to succeed",
116+
details=f"Was expecting an HTTP 409 response because of an incorrect version, but got {q.status_code} instead",
117+
query_timestamps=[q.request.timestamp],
118+
)
119+
except QueryError as qe:
120+
self.record_queries(qe.queries)
121+
if qe.cause_status_code == 409:
122+
# The spec explicitly requests a 409 response code for incorrect OVNs.
123+
pass
124+
else:
125+
check.record_failed(
126+
summary="Set USS availability with incorrect version failed for unexpected reason",
127+
details=f"Was expecting an HTTP 409 response because of an incorrect version, but got {qe.cause_status_code} instead",
128+
query_timestamps=qe.query_timestamps,
129+
)
130+
self.end_test_step()

0 commit comments

Comments
 (0)