Skip to content

Commit

Permalink
Pull Request for Fully Tested Async Client and Utils (#4)
Browse files Browse the repository at this point in the history
* Fully Tested Async Client and Utils

---------

Co-authored-by: cadea <cadea@CAgostinelli>
  • Loading branch information
cadeagostinelli and cadea authored Mar 7, 2024
1 parent 4385f4e commit adebd33
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 117 deletions.
7 changes: 7 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import pytest
from aioresponses import aioresponses
from fractal.matrix.async_client import FractalAsyncClient


@pytest.fixture
def test_fractal_async_client():
test_object = FractalAsyncClient()
print("work")
return test_object


@pytest.fixture
def mock_aiohttp_client():
with aioresponses() as m:
yield m

@pytest.fixture()
def mock_async_context_manager():
class AsyncContextManager:
Expand Down
2 changes: 0 additions & 2 deletions fractal/matrix/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ async def get_room_invites(self) -> Dict[str, InviteInfo]:
# save previous next batch since sync will replace it.
prev_next_batch = self.next_batch
res = await self.sync(since=None, timeout=0, sync_filter=invite_filter())
print(f"RES IS ============== {res}")
if isinstance(res, SyncError):
raise Exception(res.message)
# restore previous next batch
Expand Down Expand Up @@ -255,7 +254,6 @@ async def register_with_token(
# register will replace the access token that's on the client with the one returned
# from a successful registration. We want to keep the original access token.
self.access_token = access_token

if disable_ratelimiting:
await self.disable_ratelimiting(matrix_id)

Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ pytest-mock = { version = "^3.11.1", optional = true }
aioresponses = {version = "^0.7.6", optional = true}
ipython = { version = "^8.17.2", optional = true }


[tool.poetry.extras]
dev = ["pytest-django", "pytest", "pytest-cov", "pytest-mock", "pytest-asyncio", "ipython"]
dev = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-mock", "ipython", "pytest-benchmark", "aioresponses"]


[build-system]
requires = ["poetry-core"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from nio import (
RoomGetStateEventError,
RoomGetStateEventResponse,
RoomInviteError,
RoomInviteResponse,
RoomPutStateError,
RoomPutStateResponse,
Expand Down Expand Up @@ -56,6 +57,16 @@ async def test_invite_send_invite():
)


async def test_invite_roominviteerror():
sample_user_id = "@sample_user:sample_domain"
sample_room_id = "sample_id"
client = FractalAsyncClient()
client.room_invite = AsyncMock(return_value=RoomInviteError("Room Invite Failed"))
with pytest.raises(Exception) as e:
await client.invite(user_id=sample_user_id, room_id=sample_room_id, admin=True)
assert "Room Invite Failed" in str(e.value)


async def test_invite_raise_exception_for_userID():
sample_user_id = "sample_user:sample_domain"
sample_room_id = "sample_id"
Expand Down Expand Up @@ -99,7 +110,6 @@ async def test_invite_room_get_state_event_error_when_has_message():
assert "Error message" in str(e.value)


# @pytest.mark.skip("Having trouble reaching the else condition and testing the exception")
async def test_invite_room_get_state_event_error_when_no_message():
sample_user_id = "@sample_user:sample_domain"
sample_room_id = "sample_id"
Expand Down
227 changes: 197 additions & 30 deletions tests/test_matrix.py → tests/fractal-async-client/test_matrix.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
import asyncio
import os
from builtins import super
from copy import deepcopy
from unittest.mock import AsyncMock, MagicMock, patch

import aiohttp
import pytest
from aioresponses import aioresponses
from fractal.matrix import MatrixClient, get_homeserver_for_matrix_id
from fractal.matrix.async_client import FractalAsyncClient
from fractal.matrix.async_client import FractalAsyncClient, parse_matrix_id
from fractal.matrix.exceptions import (
UnknownDiscoveryInfoException,
WellKnownNotFoundException,
)
from nio import (
AsyncClient,
DeviceList,
DeviceOneTimeKeyCount,
DiscoveryInfoError,
DiscoveryInfoResponse,
InviteInfo,
JoinError,
JoinResponse,
PresenceEvent,
RegisterResponse,
RoomInfo,
Rooms,
SyncError,
SyncResponse,
Timeline,
TransferMonitor,
UploadError,
UploadResponse,
)
from nio.http import TransportResponse
from nio.responses import RegisterErrorResponse


async def test_decorator_async_context_manager_raises():
Expand Down Expand Up @@ -206,17 +217,43 @@ async def test_get_room_invites_sync_error():
assert "Error with request" in str(e.value)


@pytest.mark.skip("Either my logic is wrong or the get_room_invites is bugged")
async def test_get_room_invites_save_prev_next_batch():
async def test_get_room_invites_return_inviteinfo():
client = FractalAsyncClient()
client.next_batch = "sample_batch_value"
mock_sync_response = {"rooms": {"invite": {"room_id_1": {}, "room_id_2": {}}}}
# we create a mock of sync and make it return our dictionary
with patch.object(client, "sync", new=AsyncMock(return_value=mock_sync_response)):
invites_dict = await client.get_room_invites()
expected_invites_dict = mock_sync_response["rooms"]["invite"]
assert client.next_batch == "sample_batch_value"
assert invites_dict == expected_invites_dict
sample_next_batch = "sample_batch_value"
rooms = Rooms(
invite={"invite_room_id": InviteInfo(invite_state=[])},
join={
"join_room_id": RoomInfo(
timeline=Timeline(events=[], limited=True, prev_batch=""),
state=[],
ephemeral=[],
account_data=[],
)
},
leave={
"leave_room_id": RoomInfo(
timeline=Timeline(events=[], limited=True, prev_batch=""),
state=[],
ephemeral=[],
account_data=[],
)
},
)
devicelist = DeviceList(changed=[], left=[])
devicecount = DeviceOneTimeKeyCount(curve25519=None, signed_curve25519=None)
client.sync = AsyncMock(
return_value=SyncResponse(
next_batch=sample_next_batch,
rooms=rooms,
device_key_count=devicecount,
device_list=devicelist,
to_device_events=[],
presence_events=[],
)
)
result = await client.get_room_invites()
expected_invite_info = {"invite_room_id": InviteInfo(invite_state=[])}
assert result == expected_invite_info


async def test_join_room_logger():
Expand All @@ -228,6 +265,16 @@ async def test_join_room_logger():
mock_logger.info.assert_called_once_with(f"Joining room: {room_id}")


async def test_join_room_join_response():
client = FractalAsyncClient()
room_id = "sample_room_id"
join_response = JoinResponse(room_id=room_id)
client.join = AsyncMock(return_value=join_response)
await client.join_room(room_id=room_id)
client.join.assert_called_once_with(room_id)
assert await client.join_room(room_id=room_id) is None


async def test_join_room_join_error():
client = FractalAsyncClient()
client.join = AsyncMock(return_value=JoinError("Failed to join room"))
Expand All @@ -237,39 +284,159 @@ async def test_join_room_join_error():
assert "Failed to join room" in str(e.value)


@pytest.mark.skip("Don't know how to use aiohttp")
async def test_disable_ratelimiting_url_creation():
async def test_disable_ratelimiting_post_mock_correct(mock_aiohttp_client):
client = FractalAsyncClient()
matrix_id = "sample_matrix_id"
request_url = f"{client.homeserver}/_synapse/admin/v1/users/{matrix_id}/override_ratelimit"
mock_aiohttp_client.post(request_url, status=200)
await client.disable_ratelimiting(matrix_id=matrix_id)
mock_aiohttp_client.assert_called_with(
request_url,
method="POST",
headers={"Authorization": f"Bearer {client.access_token}"},
json={},
)


@pytest.mark.skip(
"Type error, either lack of knowledge of aiohttp or bug in disable_ratelimiting"
)
async def test_disable_ratelimiting_logger():
async def test_disable_ratelimiting_override_error(mock_aiohttp_client):
client = FractalAsyncClient()
matrix_id = "sample_matrix_id"
request_url = f"{client.homeserver}/_synapse/admin/v1/users/{matrix_id}/override_ratelimit"
status = 500
mock_aiohttp_client.post(request_url, status=status)
with pytest.raises(Exception) as e:
await client.disable_ratelimiting(matrix_id=matrix_id)
assert f"Failed to override rate limit. Error Response status {status}: " in str(e.value)


async def test_disable_ratelimiting_logger(mock_aiohttp_client):
client = FractalAsyncClient()
matrix_id = "sample_matrix_id"
request_url = f"{client.homeserver}/_synapse/admin/v1/users/{matrix_id}/override_ratelimit"
mock_aiohttp_client.post(request_url, status=200)
with patch("fractal.matrix.async_client.logger", new=MagicMock()) as mock_logger:
await client.disable_ratelimiting(matrix_id=matrix_id)
mock_logger.info.assert_called_with("Rate limit override successful.")
mock_aiohttp_client.assert_called_with(
request_url,
method="POST",
headers={"Authorization": f"Bearer {client.access_token}"},
json={},
)


async def test_generate_registration_token_post_mock(mock_aiohttp_client):
client = FractalAsyncClient()
request_url = f"{client.homeserver}/_synapse/admin/v1/registration_tokens/new"
token_value = "sample_token"
expected_payload = {"token": token_value}
mock_aiohttp_client.post(request_url, status=200, payload=expected_payload)
token = await client.generate_registration_token()
assert isinstance(token, str)
mock_aiohttp_client.assert_called_once_with(
request_url,
method="POST",
headers={"Authorization": f"Bearer {client.access_token}"},
json={},
)


async def test_generate_registration_token_override_error(mock_aiohttp_client):
client = FractalAsyncClient()
request_url = f"{client.homeserver}/_synapse/admin/v1/registration_tokens/new"
status = 500
mock_aiohttp_client.post(request_url, status=status)
with patch("fractal.matrix.async_client.logger", new=MagicMock()) as mock_logger:
with pytest.raises(Exception):
await client.generate_registration_token()
mock_logger.error.assert_called_with(
f"Failed to override rate limit. Error Response status {status}: "
)


async def test_register_with_token_username_created_and_parent_register_with_token_called():
client = FractalAsyncClient()
matrix_id = "sample_matrix_id"
url = f"https://_synapse/admin/v1/users/{matrix_id}/override_ratelimit"
mock_post = AsyncMock(return_value=MagicMock(ok=True, text=AsyncMock(return_value="OK")))
password = "sample_password"
registration_token = "sample_registration_token"
with patch(
"fractal.matrix.async_client.aiohttp.ClientSession.post", new=mock_post
) as mock_post_call:
with patch("fractal.matrix.async_client.logger", new=MagicMock()) as mock_logger:
await client.disable_ratelimiting(matrix_id=matrix_id)
mock_logger.info.assert_called_once_with("Rate limit override successful.")
mock_post_call.assert_called_once_with(
url, json={}, headers={"Authorization": f"Bearer {client.access_token}"}
"fractal.matrix.async_client.parse_matrix_id",
new=MagicMock(return_value=["sample_username"]),
) as mock_parse:
with patch(
"fractal.matrix.async_client.AsyncClient.register_with_token", new=AsyncMock()
) as mock_register_with_token:
client.disable_ratelimiting = AsyncMock()
await client.register_with_token(
matrix_id=matrix_id,
password=password,
registration_token=registration_token,
)
mock_register_with_token.assert_called_once_with(
"sample_username", password, registration_token, device_name=""
)


@pytest.mark.skip("come back to")
async def test_register_with_token():
async def test_register_with_token_registererrorresponse():
client = FractalAsyncClient()
matrix_id = "sample_matrix_id"
password = "sample_password"
registration_token = "sample_registration_token"
client.register_with_token = AsyncMock()
with patch("fractal.matrix.async_client.parse_matrix_id", new=MagicMock()) as mock_parse:
with patch(
"fractal.matrix.async_client.AsyncClient.register_with_token",
new=AsyncMock(return_value=RegisterErrorResponse("Error with response")),
) as mock_register_with_token:
with pytest.raises(Exception) as e:
await client.register_with_token(
matrix_id=matrix_id,
password=password,
registration_token=registration_token,
disable_ratelimiting=True,
)
assert "Error with response" in str(e)


async def test_register_with_token_disable_ratelimiting_for_user():
client = FractalAsyncClient()
matrix_id = "sample_matrix_id"
password = "sample_password"
registration_token = "sample_registration_token"
with patch("fractal.matrix.async_client.parse_matrix_id", new=MagicMock()) as mock_parse:
with patch(
"fractal.matrix.async_client.AsyncClient.register_with_token", new=AsyncMock()
) as mock_register_with_token:
client.disable_ratelimiting = AsyncMock()
await client.register_with_token(
matrix_id=matrix_id,
password=password,
registration_token=registration_token,
)
client.disable_ratelimiting.assert_called_once_with(matrix_id)


async def test_register_with_token_successful_registration_access_token():
client = FractalAsyncClient()
matrix_id = "sample_matrix_id"
password = "sample_password"
registration_token = "sample_registration_token"
expected_access_token = "expected_token"
with patch("fractal.matrix.async_client.parse_matrix_id", new=MagicMock()) as mock_parse:
with patch(
"fractal.matrix.async_client.AsyncClient.register_with_token", new=AsyncMock()
) as mock_register_with_token:
mock_register_with_token.return_value = RegisterResponse(
user_id="sample_user",
device_id="sample_device",
access_token=expected_access_token,
)
client.disable_ratelimiting = AsyncMock()
access_token = await client.register_with_token(
matrix_id=matrix_id,
password=password,
registration_token=registration_token,
)
assert access_token == expected_access_token


async def test_upload_file_success_no_monitor(mock_async_context_manager):
Expand Down Expand Up @@ -326,4 +493,4 @@ async def test_upload_file_monitor_success(mock_async_context_manager):
mock_logger.info.assert_called_once_with(f"Uploading file: {file_path}")
assert "http://Someurl" in content_uri
client.upload.assert_called()
assert client.upload.call_args.kwargs["monitor"].total_size == 10
assert client.upload.call_args.kwargs["monitor"].total_size == 10
Loading

0 comments on commit adebd33

Please sign in to comment.