Skip to content

Commit

Permalink
Add tests for better exception handling (#870)
Browse files Browse the repository at this point in the history
* Add initial tests for better exception handling

* Add local tests and fix (almost all of them)

* Enable first cloud tests

* Fix fixture
  • Loading branch information
iMicknl committed Jun 7, 2023
1 parent 92f1102 commit 3ca5b6e
Show file tree
Hide file tree
Showing 26 changed files with 308 additions and 13 deletions.
33 changes: 23 additions & 10 deletions pyoverkiz/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
NoRegisteredEventListenerException,
NotAuthenticatedException,
NotSuchTokenException,
OverkizException,
ServiceUnavailableException,
SessionAndBearerInSameRequestException,
SomfyBadCredentialsException,
SomfyServiceException,
Expand Down Expand Up @@ -802,14 +804,27 @@ async def check_response(response: ClientResponse) -> None:
result = await response.json(content_type=None)
except JSONDecodeError as error:
result = await response.text()
if "Server is down for maintenance" in result:

if "is down for maintenance" in result:
raise MaintenanceException("Server is down for maintenance") from error
raise Exception(

if response.status == 503:
raise ServiceUnavailableException(result) from error

raise OverkizException(
f"Unknown error while requesting {response.url}. {response.status} - {result}"
) from error

if result.get("errorCode"):
message = result.get("error").strip("'")
# Error messages between cloud and local Overkiz servers can be slightly different
# To make it easier to have a strict match for these errors, we remove the double quotes and the period at the end.

if message := result.get("error"):
message = message.strip(
'".'
) # Change to .removesuffix when Python 3.8 support is dropped
else:
message = "" # An error message can have an empty (None) message

# {"errorCode": "AUTHENTICATION_ERROR",
# "error": "Too many requests, try again later : login with xxx@xxx.tld"}
Expand All @@ -825,7 +840,7 @@ async def check_response(response: ClientResponse) -> None:
raise NotAuthenticatedException(message)

# {"error":"Missing authorization token.","errorCode":"RESOURCE_ACCESS_DENIED"}
if message == "Missing authorization token.":
if message == "Missing authorization token":
raise MissingAuthorizationTokenException(message)

# {"error": "Server busy, please try again later. (Too many executions)"}
Expand All @@ -851,10 +866,7 @@ async def check_response(response: ClientResponse) -> None:
if message == "Cannot use JSESSIONID and bearer token in same request":
raise SessionAndBearerInSameRequestException(message)

if (
message
== "Too many attempts with an invalid token, temporarily banned."
):
if message == "Too many attempts with an invalid token, temporarily banned":
raise TooManyAttemptsBannedException(message)

if "Invalid token : " in message:
Expand All @@ -867,14 +879,15 @@ async def check_response(response: ClientResponse) -> None:
raise UnknownUserException(message)

# {"error":"Unknown object.","errorCode":"UNSPECIFIED_ERROR"}
if message == "Unknown object.":
if message == "Unknown object":
raise UnknownObjectException(message)

# {'errorCode': 'RESOURCE_ACCESS_DENIED', 'error': 'Access denied to gateway #1234-5678-1234 for action ADD_TOKEN'}
if "Access denied to gateway" in message:
raise AccessDeniedToGatewayException(message)

raise Exception(message if message else result)
# General Overkiz exception
raise OverkizException(result)

async def _refresh_token_if_expired(self) -> None:
"""Check if token is expired and request a new one."""
Expand Down
10 changes: 9 additions & 1 deletion pyoverkiz/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ class BaseOverkizException(Exception):
pass


class OverkizException(BaseOverkizException):
pass


class BadCredentialsException(BaseOverkizException):
pass

Expand All @@ -26,7 +30,11 @@ class TooManyConcurrentRequestsException(BaseOverkizException):
pass


class MaintenanceException(BaseOverkizException):
class ServiceUnavailableException(BaseOverkizException):
pass


class MaintenanceException(ServiceUnavailableException):
pass


Expand Down
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/cloud/401-not-authenticated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"errorCode": "RESOURCE_ACCESS_DENIED",
"error": "Not authenticated"
}
Empty file.
64 changes: 64 additions & 0 deletions tests/fixtures/exceptions/cloud/503-maintenance.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<html>

<head>
<style>
body {
font-family: Circular, "Helvetica Neue", Helvetica, Arial, sans-serif;
color: rgb(72, 72, 72);
}
</style>
</head>

<body style="margin:0;padding:0">
<div style="padding: 20px 25px 20px 20px"> <svg version="1.1" x="0px" y="0px" viewBox="0 0 150 150"
xml:space="preserve" width="150" height="150" xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:i="&amp;ns_ai;">
<style type="text/css" id="style18">
.st0 {
fill: none;
}

.st1 {
fill: #3D423D;
}

.st2 {
fill: #8C918C;
}

.st3 {
fill: #C8D419;
}

.st4 {
fill: #F39200;
}
</style>
<switch id="switch40">
<foreignObject requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/" x="0" y="0" width="1"
height="1"></foreignObject>
<g i:extraneous="self" id="g38">
<rect class="st0" width="965.29999" height="265.29999" id="rect20" x="0" y="0" />
<g id="g36" style="display:inline">
<g id="g34" transform="translate(-68.977383,-46.879183)">
<g id="g32">
<polygon class="st3" points="87.2,88.9 203.6,88.9 145.4,59.3 " id="polygon26" />
<polygon class="st4" points="203.6,160.8 203.6,88.9 149.8,182.7 " id="polygon28" />
<polygon class="st3" points="87.2,160.9 87.2,88.9 145.4,160.9 " id="polygon30" />
</g>
</g>
</g>
<polygon class="st2" points="87.2,160.9 145.4,59.3 87.2,88.9 " id="polygon24"
style="fill:#8c918c;fill-opacity:0.847297" transform="translate(-68.977383,-46.879183)" />
</g>
</switch>
</svg> </div>
<div
style="padding: 100px;text-align: center;font-size: 40px;background-color: #eeeeee;border-bottom: 2px solid #dddddd;border-top: 2px solid #dddddd">
<span style="font-64px: size;font-weight: bold">Oops !</span><br />
Our service is down for maintenance.<br />Please try again later.<br /> <br /> <span
style="font-64px: size;font-weight: bold;color: #bbbbbb">503</span>
</div>
</body>

</html>
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/cloud/access-denied-to-gateway.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"errorCode": "RESOURCE_ACCESS_DENIED",
"error": "Access denied to gateway #1234-5678-1234 for action ADD_TOKEN"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/cloud/bad-credentials.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"errorCode": "AUTHENTICATION_ERROR",
"error": "Bad credentials"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Missing authorization token.",
"errorCode": "RESOURCE_ACCESS_DENIED"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "\"No registered event listener.\"",
"errorCode": "UNSPECIFIED_ERROR"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"errorCode": "RESOURCE_ACCESS_DENIED",
"error": "too many concurrent requests"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/cloud/too-many-executions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Server busy, please try again later. (Too many executions)",
"errorCode": "RESOURCE_ACCESS_DENIED"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/cloud/too-many-requests.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"errorCode": "AUTHENTICATION_ERROR",
"error": "Too many requests, try again later : login with xxx@xxx.tld"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "\"No corresponding execId c6f83624-ac10-3e01-653e-2b025fee956d\"",
"errorCode": "UNSPECIFIED_ERROR"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/local/400-bad-parameters.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Bad parameters. (\"\"message\"\")",
"errorCode": "INVALID_PARAMETER"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/local/400-bus-error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Bus error",
"errorCode": "DBUS_ERROR"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Malformed \"Malformed action group\". (missing parameter)",
"errorCode": "MISSING_PARAMETERS"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/local/400-malformed-fetch-id.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Malformed \"Malformed fetch id.\". (missing parameter)",
"errorCode": "MISSING_PARAMETERS"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/local/400-missing-execution-id.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Malformed \"Missing execution id\". (missing parameter)",
"errorCode": "MISSING_PARAMETERS"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/local/400-missing-parameters.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Malformed \"Malformed devices states\". (missing parameter)",
"errorCode": "MISSING_PARAMETERS"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "\"No registered event listener.\"",
"errorCode": "UNSPECIFIED_ERROR"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/local/400-no-such-device.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "No such device : \"io://9876-1234-8767/4468654\"",
"errorCode": "NO_SUCH_DEVICE"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/local/400-unknown-object.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Unknown object.",
"errorCode": "UNSPECIFIED_ERROR"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/local/400-unspecified-error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": null,
"errorCode": "UNSPECIFIED_ERROR"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Missing authorization token.",
"errorCode": "RESOURCE_ACCESS_DENIED"
}
4 changes: 4 additions & 0 deletions tests/fixtures/exceptions/local/401-not-authenticated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"error": "Not authenticated.",
"errorCode": "RESOURCE_ACCESS_DENIED"
}
Loading

0 comments on commit 3ca5b6e

Please sign in to comment.