Skip to content

Commit

Permalink
impl delete case
Browse files Browse the repository at this point in the history
  • Loading branch information
mickmis committed Sep 21, 2023
1 parent 0026e8d commit 1ea658b
Show file tree
Hide file tree
Showing 10 changed files with 395 additions and 40 deletions.
15 changes: 12 additions & 3 deletions monitoring/monitorlib/rid.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ def openapi_flight_details_response_path(self) -> str:
else:
raise ValueError(f"Unsupported RID version '{self}'")

@property
def openapi_search_isas_response_path(self) -> str:
if self == RIDVersion.f3411_19:
return schema_validation.F3411_19.SearchIdentificationServiceAreasResponse
elif self == RIDVersion.f3411_22a:
return schema_validation.F3411_22a.SearchIdentificationServiceAreasResponse
else:
raise ValueError(f"Unsupported RID version '{self}'")

@property
def openapi_put_isa_response_path(self) -> str:
if self == RIDVersion.f3411_19:
Expand All @@ -58,11 +67,11 @@ def openapi_put_isa_response_path(self) -> str:
raise ValueError(f"Unsupported RID version '{self}'")

@property
def openapi_search_isas_response_path(self) -> str:
def openapi_delete_isa_response_path(self) -> str:
if self == RIDVersion.f3411_19:
return schema_validation.F3411_19.SearchIdentificationServiceAreasResponse
return schema_validation.F3411_19.DeleteIdentificationServiceAreaResponse
elif self == RIDVersion.f3411_22a:
return schema_validation.F3411_22a.SearchIdentificationServiceAreasResponse
return schema_validation.F3411_22a.DeleteIdentificationServiceAreaResponse
else:
raise ValueError(f"Unsupported RID version '{self}'")

Expand Down
6 changes: 6 additions & 0 deletions monitoring/monitorlib/schema_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class F3411_19(str, Enum):
PutIdentificationServiceAreaResponse = (
"components.schemas.PutIdentificationServiceAreaResponse"
)
DeleteIdentificationServiceAreaResponse = (
"components.schemas.DeleteIdentificationServiceAreaResponse"
)


class F3411_22a(str, Enum):
Expand All @@ -34,6 +37,9 @@ class F3411_22a(str, Enum):
PutIdentificationServiceAreaResponse = (
"components.schemas.PutIdentificationServiceAreaResponse"
)
DeleteIdentificationServiceAreaResponse = (
"components.schemas.DeleteIdentificationServiceAreaResponse"
)


class F3548_21(str, Enum):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,6 @@ def _delete_isa_if_exists(self):
def _get_isa_by_id_step(self):
self.begin_test_step("Get ISA by ID")

# TODO: add + use get_isa step

with self.check(
"Successful ISA query", [self._dss_wrapper.participant_id]
) as check:
Expand Down Expand Up @@ -152,7 +150,7 @@ def _create_and_check_isa_case(self):
def _create_isa_step():
self.begin_test_step("Create ISA")

with self.check("ISA created", [self._dss.participant_id]) as check:
with self.check("ISA created", [self._dss_wrapper.participant_id]) as check:
isa_change = self._dss_wrapper.put_isa(
main_check=check,
area_vertices=self._isa_area,
Expand Down Expand Up @@ -371,17 +369,116 @@ def _search_huge_area_step():

_search_huge_area_step()

def _search_isa_loop_step():
self.begin_test_step("Search ISA with loop")

with self.check(
"Search request rejected", [self._dss_wrapper.participant_id]
) as check:
search_area_loop = self._isa_area.copy()
search_area_loop.append(search_area_loop[0])
_ = self._dss_wrapper.search_isas_expect_response_code(
check,
expected_error_codes={400},
area=search_area_loop,
)

self.end_test_step()

_search_isa_loop_step()

self.end_test_case()

def _delete_isa_case(self):
self.begin_test_case("Delete ISA")

# TODO: Delete with wrong version
# TODO: Delete with empty version
# TODO: Delete ISA
# TODO: Get ISA by ID
# TODO: Search ISA
# TODO: Search ISA with loop
def _delete_wrong_version_step():
self.begin_test_step("Delete with wrong version")

with self.check(
"Delete request rejected", [self._dss_wrapper.participant_id]
) as check:
_ = self._dss_wrapper.del_isa_expect_response_code(
check,
expected_error_codes={409},
isa_id=self._isa_id,
isa_version=self._isa_version[1:-1],
)

self.end_test_step()

_delete_wrong_version_step()

def _delete_empty_version_step():
self.begin_test_step("Delete with empty version")

with self.check(
"Delete request rejected", [self._dss_wrapper.participant_id]
) as check:
_ = self._dss_wrapper.del_isa_expect_response_code(
check,
expected_error_codes={400},
isa_id=self._isa_id,
isa_version="",
)

self.end_test_step()

_delete_empty_version_step()

def _delete_step():
self.begin_test_step("Delete ISA")

with self.check("ISA deleted", [self._dss_wrapper.participant_id]) as check:
_ = self._dss_wrapper.del_isa(
check, isa_id=self._isa_id, isa_version=self._isa_version
)

self.end_test_step()

_delete_step()

def _get_deleted_isa_by_id_step():
self.begin_test_step("Get deleted ISA by ID")

with self.check(
"ISA not found", [self._dss_wrapper.participant_id]
) as check:
_ = self._dss_wrapper.get_isa_expect_response_code(
check,
expected_error_codes={404},
isa_id=self._isa_id,
)

self.end_test_step()

_get_deleted_isa_by_id_step()

def _search_isa_step():
self.begin_test_step("Search ISA")

with self.check(
"Successful ISAs search", [self._dss_wrapper.participant_id]
) as check:
isas = self._dss_wrapper.search_isas(
check,
area=self._isa_area,
)

with self.check(
"ISA not returned by search", [self._dss_wrapper.participant_id]
) as check:
if self._isa_id in isas.isas.keys():
check.record_failed(
f"ISAs search returned deleted ISA {self._isa_id}",
severity=Severity.High,
details=f"Search in area {self._isa_area} returned ISAs {isas.isas.keys()}",
query_timestamps=[isas.dss_query.query.request.timestamp],
)

self.end_test_step()

_search_isa_step()

self.end_test_case()

Expand Down
153 changes: 129 additions & 24 deletions monitoring/uss_qualifier/scenarios/astm/netrid/dss_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,36 @@ def get_isa(
"DSS query was not successful, but a High Severity issue didn't interrupt execution"
)

def get_isa_expect_response_code(
self,
check: PendingCheck,
expected_error_codes: Set[int],
isa_id: str,
) -> FetchedISA:
"""Attempt to fetch an ISA at the DSS, and expect the specified HTTP response code.
A check fail is considered of high severity and as such will raise a ScenarioCannotContinueError.
:return: the DSS response
"""

isa = fetch.isa(
isa_id=isa_id,
rid_version=self._dss.rid_version,
session=self._dss.client,
server_id=self._dss.participant_id,
)

self._handle_query_result(
check=check,
q=isa,
required_status_code=expected_error_codes,
fail_msg=f"Fetching ISA {isa_id} resulted in an HTTP code not in {expected_error_codes}",
fail_details=f"ISA: ID {isa_id}",
)

return isa

def put_isa(
self,
main_check: PendingCheck,
Expand Down Expand Up @@ -365,46 +395,121 @@ def _fail_sub_check(

def del_isa(
self,
check: PendingCheck,
main_check: PendingCheck,
isa_id: str,
isa_version: str,
) -> ISAChange:
"""Delete an ISA at the DSS.
A check fail is considered of high severity and as such will raise a ScenarioCannotContinueError.
Query failure will fail the provided main check. If the query is successful, the sub-checks of the test step
described in '[v19|v22a]/dss/test_steps/delete_isa.md' are performed. Some of those might fail the main check.
:return: the DSS response
"""

try:
del_isa = mutate.delete_isa(
isa_id=isa_id,
isa_version=isa_version,
rid_version=self._dss.rid_version,
utm_client=self._dss.client,
server_id=self._dss.participant_id,
del_isa = mutate.delete_isa(
isa_id=isa_id,
isa_version=isa_version,
rid_version=self._dss.rid_version,
utm_client=self._dss.client,
server_id=self._dss.participant_id,
)
self._handle_query_result(
main_check, del_isa.dss_query, f"Failed to delete ISA {isa_id}"
)
for notification_query in del_isa.notifications.values():
self._scenario.record_query(notification_query.query)

dss_id = [self._dss.participant_id]
t_dss = del_isa.dss_query.query.request.timestamp
dss_isa = del_isa.dss_query.isa

# sub-checks that do not fail the main check
with self._scenario.check("ISA response format", dss_id) as sub_check:
errors = schema_validation.validate(
self._dss.rid_version.openapi_path,
self._dss.rid_version.openapi_delete_isa_response_path,
del_isa.dss_query.query.response.json,
)
if errors:
details = "\n".join(f"[{e.json_path}] {e.message}" for e in errors)
sub_check.record_failed(
"Delete ISA response format was invalid",
Severity.Medium,
"Found the following schema validation errors in the DSS response:\n"
+ details,
query_timestamps=[t_dss],
)

self._handle_query_result(
check, del_isa.dss_query, f"Failed to delete ISA {isa_id}"
# sub-checks that fail the main check
def _fail_sub_check(
_sub_check: PendingCheck, _summary: str, _details: str
) -> None:
"""Fails with Medium severity the sub_check and with High severity the main check."""

_sub_check.record_failed(
summary=_summary,
severity=Severity.Medium,
details=_details,
query_timestamps=[t_dss],
)
main_check.record_failed(
summary=f"Delete ISA request succeeded, but the DSS response is not valid: {_summary}",
severity=Severity.High,
details=_details,
query_timestamps=[t_dss],
)

if isa_version != del_isa.dss_query.isa.version:
check.record_failed(
summary=f"Deleted ISA did not match",
severity=Severity.High,
participants=[self._dss.participant_id],
details=f"DSS reported deletion of version {isa_version} while expecting {del_isa.dss_query.isa.version}",
query_timestamps=[del_isa.dss_query.query.request.timestamp],
with self._scenario.check("ISA ID matches", dss_id) as sub_check:
if isa_id != dss_isa.id:
_fail_sub_check(
sub_check,
"Deleted ISA ID did not match",
f"Expected ISA ID {isa_id} but got {dss_isa.id}",
)
else:
return del_isa

except QueryError as e:
self._handle_query_error(check, e)
raise RuntimeError(
"DSS query was not successful, but a High Severity issue didn't interrupt execution"
with self._scenario.check("ISA version matches", dss_id) as sub_check:
if dss_isa.version != isa_version:
_fail_sub_check(
sub_check,
"Deleted ISA version did not match",
f"Expected ISA version {isa_version} but got {dss_isa.version}",
)

return del_isa

def del_isa_expect_response_code(
self,
main_check: PendingCheck,
expected_error_codes: Set[int],
isa_id: str,
isa_version: str,
) -> ISAChange:
"""Attempt to delete an ISA at the DSS, and expect the specified HTTP response code.
A check fail is considered of high severity and as such will raise a ScenarioCannotContinueError.
:return: the DSS response
"""

del_isa = mutate.delete_isa(
isa_id=isa_id,
isa_version=isa_version,
rid_version=self._dss.rid_version,
utm_client=self._dss.client,
server_id=self._dss.participant_id,
)

self._handle_query_result(
check=main_check,
q=del_isa.dss_query,
required_status_code=expected_error_codes,
fail_msg=f"Deleting ISA {isa_id} resulted in an HTTP code not in {expected_error_codes}",
fail_details=f"ISA: ID {isa_id}; version {isa_version}",
)

return del_isa

def cleanup_isa(
self,
check: PendingCheck,
Expand Down
Loading

0 comments on commit 1ea658b

Please sign in to comment.