Skip to content

Commit 7ff6b5c

Browse files
committed
Add/Update unit tests for Azure
This commit updates and creates new tests to make sure the new implemented exception handlers for retrying on in progress submission/conflict are properly working. Assisted-by: Cursor Signed-off-by: Jonathan Gangi <[email protected]>
1 parent 80fc1ce commit 7ff6b5c

File tree

3 files changed

+174
-11
lines changed

3 files changed

+174
-11
lines changed

tests/ms_azure/conftest.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,49 @@ def job_details_completed_failure(errors: List[Dict[str, Any]]) -> Dict[str, Any
9191
return job_details(status="completed", result="failed", errors=errors)
9292

9393

94+
@pytest.fixture
95+
def job_details_completed_conflict(errors_conflict: List[Dict[str, Any]]) -> Dict[str, Any]:
96+
return job_details(status="completed", result="failed", errors=errors_conflict)
97+
98+
99+
@pytest.fixture
100+
def job_details_completed_running_submission(
101+
errors_running_submission: List[Dict[str, Any]],
102+
) -> Dict[str, Any]:
103+
return job_details(status="completed", result="failed", errors=errors_running_submission)
104+
105+
94106
@pytest.fixture
95107
def errors() -> List[Dict[str, Any]]:
96108
return [
97109
{
110+
"resourceId": "resource-id",
111+
"code": "internalServerError",
112+
"message": "A catastrophic error occurred.",
113+
"details": [{"code": "invalidResource", "message": "Failure for resource"}],
114+
}
115+
]
116+
117+
118+
@pytest.fixture
119+
def errors_running_submission() -> List[Dict[str, Any]]:
120+
return [
121+
{
122+
"resourceId": "resource-id",
123+
"code": "internalServerError",
124+
"message": "An In Progress submission 1234567890 already exists.",
125+
"details": [{"code": "invalidResource", "message": "Failure for resource"}],
126+
}
127+
]
128+
129+
130+
@pytest.fixture
131+
def errors_conflict() -> List[Dict[str, Any]]:
132+
return [
133+
{
134+
"resourceId": "resource-id",
98135
"code": "conflict",
99-
"message": "Error message",
136+
"message": "The submission cannot be pushed to live as its not the latest submission.",
100137
"details": [{"code": "invalidResource", "message": "Failure for resource"}],
101138
}
102139
]
@@ -119,6 +156,7 @@ def configure_success_response() -> Dict[str, Any]:
119156
def configure_failure_response() -> Dict[str, Any]:
120157
return {
121158
"error": {
159+
"resourceId": "resource-id",
122160
"code": "badRequest",
123161
"message": "Invalid configuration: schema validation failed",
124162
"details": [
@@ -599,3 +637,17 @@ def job_details_completed_failure_obj(
599637
job_details_completed_failure: Dict[str, Any],
600638
) -> ConfigureStatus:
601639
return ConfigureStatus.from_json(job_details_completed_failure)
640+
641+
642+
@pytest.fixture
643+
def job_details_completed_conflict_obj(
644+
job_details_completed_conflict: Dict[str, Any],
645+
) -> ConfigureStatus:
646+
return ConfigureStatus.from_json(job_details_completed_conflict)
647+
648+
649+
@pytest.fixture
650+
def job_details_completed_running_submission_obj(
651+
job_details_completed_running_submission: Dict[str, Any],
652+
) -> ConfigureStatus:
653+
return ConfigureStatus.from_json(job_details_completed_running_submission)

tests/ms_azure/test_service.py

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22
import logging
33
from copy import deepcopy
4-
from typing import Any, Dict, List
4+
from typing import Any, Dict
55
from unittest import mock
66

77
import pytest
@@ -12,7 +12,7 @@
1212
from tenacity.stop import stop_after_attempt
1313

1414
from cloudpub.common import BaseService
15-
from cloudpub.error import InvalidStateError, NotFoundError
15+
from cloudpub.error import ConflictError, InvalidStateError, NotFoundError, RunningSubmissionError
1616
from cloudpub.models.ms_azure import (
1717
ConfigureStatus,
1818
CustomerLeads,
@@ -213,6 +213,14 @@ def test_wait_for_job_completion_successful_completion(
213213
assert f"Job {job_id} failed" not in caplog.text
214214
assert f"Job {job_id} succeeded" in caplog.text
215215

216+
@pytest.mark.parametrize(
217+
"error_name",
218+
[
219+
"job_details_completed_failure_obj",
220+
"job_details_completed_conflict_obj",
221+
"job_details_completed_running_submission_obj",
222+
],
223+
)
216224
@mock.patch("cloudpub.ms_azure.utils.is_azure_job_not_complete")
217225
@mock.patch("cloudpub.ms_azure.AzureService._query_job_details")
218226
def test_get_job_details_after_failed_completion(
@@ -223,20 +231,26 @@ def test_get_job_details_after_failed_completion(
223231
caplog: LogCaptureFixture,
224232
job_details_running_obj: ConfigureStatus,
225233
job_details_completed_failure_obj: ConfigureStatus,
226-
errors: List[Dict[str, Any]],
234+
job_details_completed_conflict_obj: ConfigureStatus,
235+
job_details_completed_running_submission_obj: ConfigureStatus,
236+
error_name: str,
237+
request: pytest.FixtureRequest,
227238
) -> None:
239+
228240
mock_job_details.side_effect = [
229241
job_details_running_obj,
230242
job_details_running_obj,
231243
job_details_running_obj,
232-
job_details_completed_failure_obj,
244+
request.getfixturevalue(error_name),
233245
job_details_running_obj,
234246
]
235247

236248
azure_service._wait_for_job_completion.retry.sleep = mock.Mock() # type: ignore
237249
job_id = "job_id_111"
238250
with caplog.at_level(logging.ERROR):
239-
with pytest.raises(InvalidStateError) as e_info:
251+
with pytest.raises(
252+
(InvalidStateError, RunningSubmissionError, ConflictError)
253+
) as e_info:
240254
azure_service._wait_for_job_completion(job_id=job_id)
241255
assert f"Job {job_id} failed: \n" in str(e_info.value)
242256
assert mock_job_details.call_count == 4
@@ -858,7 +872,7 @@ def test_publish_preview_success_on_retry(
858872
None,
859873
mock.MagicMock(), # Success on 3rd call
860874
]
861-
# Remove the retry sleep
875+
# Remove the retry sleeptest_publish_preview_fail_on_retry
862876
azure_service._publish_preview.retry.sleep = mock.Mock() # type: ignore
863877

864878
# Test
@@ -888,7 +902,18 @@ def test_publish_preview_fail_on_retry(
888902
"jobId": "1",
889903
"jobStatus": "completed",
890904
"jobResult": "failed",
891-
"errors": ["failure1", "failure2"],
905+
"errors": [
906+
{
907+
"resourceId": "resource-id",
908+
"code": "internalServerError",
909+
"message": "failure1",
910+
},
911+
{
912+
"resourceId": "resource-id",
913+
"code": "internalServerError",
914+
"message": "failure2",
915+
},
916+
],
892917
}
893918
)
894919
mock_is_sbpreview.return_value = False
@@ -898,7 +923,7 @@ def test_publish_preview_fail_on_retry(
898923
azure_service._publish_preview.retry.sleep = mock.Mock() # type: ignore
899924
expected_err = (
900925
f"Failed to submit the product {product_obj.id} to preview. "
901-
"Status: failed Errors: failure1\nfailure2"
926+
"Status: failed Errors: internalServerError: failure1\ninternalServerError: failure2"
902927
)
903928

904929
# Test
@@ -949,7 +974,18 @@ def test_publish_live_fail_on_retry(
949974
"jobId": "1",
950975
"jobStatus": "completed",
951976
"jobResult": "failed",
952-
"errors": ["failure1", "failure2"],
977+
"errors": [
978+
{
979+
"resourceId": "resource-id",
980+
"code": "internalServerError",
981+
"message": "failure1",
982+
},
983+
{
984+
"resourceId": "resource-id",
985+
"code": "internalServerError",
986+
"message": "failure2",
987+
},
988+
],
953989
}
954990
)
955991
mock_subst.side_effect = [err_resp for _ in range(3)]
@@ -958,7 +994,7 @@ def test_publish_live_fail_on_retry(
958994
azure_service._publish_live.retry.sleep = mock.Mock() # type: ignore
959995
expected_err = (
960996
f"Failed to submit the product {product_obj.id} to live. "
961-
"Status: failed Errors: failure1\nfailure2"
997+
"Status: failed Errors: internalServerError: failure1\ninternalServerError: failure2"
962998
)
963999

9641000
# Test

tests/ms_azure/test_utils.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
)
1616
from cloudpub.ms_azure.utils import (
1717
AzurePublishingMetadata,
18+
check_for_conflict,
19+
check_for_running_submission,
1820
create_disk_version_from_scratch,
1921
get_image_type_mapping,
2022
is_azure_job_not_complete,
@@ -580,3 +582,76 @@ def test_create_disk_version_from_scratch_arm64(
580582
res.vm_images = sorted(res.vm_images, key=attrgetter("image_type"))
581583

582584
assert res == disk_version_arm64_obj
585+
586+
@pytest.mark.parametrize(
587+
"error,expected_result",
588+
[
589+
(
590+
{
591+
"code": "conflict",
592+
"message": "The submission cannot be pushed to live as its not the latest submission.", # noqa: E501
593+
},
594+
True,
595+
),
596+
(
597+
{
598+
"code": "internalServerError",
599+
"message": "An In Progress submission 1234567890 already exists.",
600+
},
601+
False,
602+
),
603+
(
604+
{
605+
"code": "unknownError",
606+
"message": "An In Progress submission 1234567890 already exists.",
607+
},
608+
False,
609+
),
610+
({"code": "conflict", "message": "Something else happened"}, False),
611+
],
612+
)
613+
def test_check_for_conflict(self, error: Dict[str, Any], expected_result: bool) -> None:
614+
err_obj = ConfigureStatus.from_json(
615+
{
616+
"jobId": "1",
617+
"jobStatus": "completed",
618+
"jobResult": "failed",
619+
"errors": [error],
620+
}
621+
)
622+
assert err_obj
623+
assert check_for_conflict(err_obj) == expected_result
624+
625+
@pytest.mark.parametrize(
626+
"error,expected_result",
627+
[
628+
(
629+
{
630+
"code": "internalServerError",
631+
"message": "An In Progress submission 1234567890 already exists.",
632+
},
633+
True,
634+
),
635+
(
636+
{
637+
"code": "unknownError",
638+
"message": "An In Progress submission 1234567890 already exists.",
639+
},
640+
False,
641+
),
642+
({"code": "conflict", "message": "Something else happened"}, False),
643+
],
644+
)
645+
def test_check_for_running_submission(
646+
self, error: Dict[str, Any], expected_result: bool
647+
) -> None:
648+
err_obj = ConfigureStatus.from_json(
649+
{
650+
"jobId": "1",
651+
"jobStatus": "completed",
652+
"jobResult": "failed",
653+
"errors": [error],
654+
}
655+
)
656+
assert err_obj
657+
assert check_for_running_submission(err_obj) == expected_result

0 commit comments

Comments
 (0)