From 817764c805e38b456bc72403b087875ef79a6f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joonatan=20M=C3=A4kinen?= Date: Thu, 23 Mar 2023 13:58:04 +0200 Subject: [PATCH 1/3] Add different api unit tests --- tests/common/mockups.py | 2 + tests/request/test_api.py | 80 ++++++++++++++++++++++++++++++++------- tests/sharing/test_api.py | 70 +++++++++++++++++++++++++++++++++- tests/ui_unit/test_api.py | 22 ++++++++++- 4 files changed, 158 insertions(+), 16 deletions(-) diff --git a/tests/common/mockups.py b/tests/common/mockups.py index caa51b47e..eaa56102f 100644 --- a/tests/common/mockups.py +++ b/tests/common/mockups.py @@ -39,6 +39,7 @@ def setUp(self): "token": "test-token-1", "endpoint": "https://test-endpoint-1/v1/AUTH_test-id-1", "tainted": False, + "runner": "test-runner" }, } self.aiohttp_session_get_session_mock = unittest.mock.AsyncMock() @@ -71,6 +72,7 @@ def setUp(self): "set_origin_address": "https://localhost/login/websso", "has_trust": True, "upload_external_endpoint": "http://test-endpoint:9092/", + "upload_internal_endpoint": "http://test-endpoint:9093/", "oidc_enabled": False, } self.patch_setd = unittest.mock.patch( diff --git a/tests/request/test_api.py b/tests/request/test_api.py index 77219b7f2..7516848d0 100644 --- a/tests/request/test_api.py +++ b/tests/request/test_api.py @@ -2,9 +2,9 @@ import unittest +from unittest import mock from types import SimpleNamespace - import aiohttp @@ -14,6 +14,10 @@ handle_user_made_request_listing, handle_container_request_listing, handle_user_share_request_delete, + handle_user_add_token, + handle_user_delete_token, + handle_user_list_tokens, + handle_health_check ) @@ -28,20 +32,28 @@ def setUp(self): "db_conn": SimpleNamespace( **{ "add_request": unittest.mock.AsyncMock(), + "add_token": unittest.mock.AsyncMock(), "get_request_owned": unittest.mock.AsyncMock(), "get_request_made": unittest.mock.AsyncMock(), "get_request_container": unittest.mock.AsyncMock(), "delete_request": unittest.mock.AsyncMock(), + "get_tokens": unittest.mock.AsyncMock([]), + "revoke_token": unittest.mock.AsyncMock(), + "pool": None, } ) }, "query": { "owner": "AUTH_otherexample", + "token": "user_token" }, "match_info": { "container": "test", "user": "test", + "project": "test", + "id": "test", }, + "post": unittest.mock.AsyncMock(return_value={}), } ) @@ -50,33 +62,75 @@ def setUp(self): "swift_browser_ui.request.api.aiohttp.web.json_response", new=self.json_mock ) - async def test_endpoint_has_access_correct(self): - """Test the has-access endpoint for conformity.""" + async def test_endpoint_share_request_post_correct(self): + """Test the share_request_post endpoint for conformity.""" with self.patch_json_dump: await handle_share_request_post(self.mock_request) self.json_mock.assert_called_once() - async def test_endpoint_access_details_correct(self): - """Test the access-details endpoint for conformity.""" + async def test_endpoint_user_owned_request_listing_correct(self): + """Test the user_owned_request_listing endpoint for conformity.""" with self.patch_json_dump: await handle_user_owned_request_listing(self.mock_request) self.json_mock.assert_called_once() - async def test_endpoint_gave_access_correct(self): - """Test the gave-access endpoint for conformity.""" + async def test_endpoint_user_made_request_listing(self): + """Test the user_made_request_listing endpoint for conformity.""" with self.patch_json_dump: await handle_user_made_request_listing(self.mock_request) self.json_mock.assert_called_once() - async def test_endpoint_shared_details_correct(self): - """Test the shared_details endpoint for conformity.""" + async def test_endpoint_container_request_listing(self): + """Test the container_request_listing endpoint for conformity.""" with self.patch_json_dump: await handle_container_request_listing(self.mock_request) self.json_mock.assert_called_once() - async def test_endpoint_share_container_correct(self): - """Test the share_container endpoint for conformity.""" - self.json_mock.return_value.status = 200 + async def test_endpoint_user_share_request_delete(self): + """Test the user_share_request_delete endpoint for conformity.""" with self.patch_json_dump: resp = await handle_user_share_request_delete(self.mock_request) - print(resp) + self.assertEqual(resp.status, 200) + + async def test_endpoint_handle_user_add_token(self): + """Test the handle_user_add_token endpoint for conformity.""" + with self.patch_json_dump: + resp = await handle_user_add_token(self.mock_request) + self.assertEqual(resp.status, 200) + + # Also test when no token is present in query + del self.mock_request.query["token"] + with self.patch_json_dump: + with self.assertRaises(aiohttp.web.HTTPBadRequest): + await handle_user_add_token(self.mock_request) + + async def test_endpoint_handle_user_delete_token(self): + """Test the handle_user_delete_token endpoint for conformity.""" + with self.patch_json_dump: + resp = await handle_user_delete_token(self.mock_request) + self.assertEqual(resp.status, 200) + + async def test_endpoint_handle_user_list_tokens(self): + """Test the handle_user_list_tokens endpoint for conformity.""" + with self.patch_json_dump: + await handle_user_list_tokens(self.mock_request) + self.json_mock.assert_called_once() + + async def test_endpoint_handle_health_check(self): + """Test the handle_health_check endpoint for conformity.""" + with self.patch_json_dump: + await handle_health_check(self.mock_request) + + self.mock_request.app["db_conn"].pool = {} + with self.patch_json_dump: + await handle_health_check(self.mock_request) + + del self.mock_request.app["db_conn"].pool + with self.patch_json_dump: + await handle_health_check(self.mock_request) + + calls = [ + unittest.mock.call({'status': 'Ok'}), + unittest.mock.call({"status": "Degraded", "degraded": ["database"]}) + ] + self.json_mock.assert_has_calls(calls) diff --git a/tests/sharing/test_api.py b/tests/sharing/test_api.py index 24f1ccf42..b93bd8c5c 100644 --- a/tests/sharing/test_api.py +++ b/tests/sharing/test_api.py @@ -3,8 +3,8 @@ from types import SimpleNamespace - import unittest +from unittest import mock import aiohttp.web @@ -17,6 +17,10 @@ edit_share_handler, delete_share_handler, delete_container_shares_handler, + handle_user_add_token, + handle_user_delete_token, + handle_user_list_tokens, + handle_health_check ) @@ -31,6 +35,7 @@ def setUp(self): "db_conn": SimpleNamespace( **{ "add_share": unittest.mock.AsyncMock(), + "add_token": unittest.mock.AsyncMock(), "edit_share": unittest.mock.AsyncMock(), "delete_share": unittest.mock.AsyncMock(), "delete_container_shares": unittest.mock.AsyncMock(), @@ -38,6 +43,9 @@ def setUp(self): "get_shared_list": unittest.mock.AsyncMock(), "get_access_container_details": unittest.mock.AsyncMock(), "get_shared_container_details": unittest.mock.AsyncMock(), + "get_tokens": unittest.mock.AsyncMock([]), + "revoke_token": unittest.mock.AsyncMock(), + "pool": None, } ), }, @@ -47,8 +55,16 @@ def setUp(self): "container": "test-container-1", "access": "r,w,l", "address": "https://placeholder.os:443", + "token": "user_token", + }, + "match_info": { + "container": "test", + "user": "test", + "owner": "test", + "project": "test", + "id": "test", }, - "match_info": {"container": "test", "user": "test", "owner": "test"}, + "post": unittest.mock.AsyncMock(return_value={}), } ) @@ -100,8 +116,58 @@ async def test_endpoint_delete_share_correct(self): resp = await delete_share_handler(self.mock_request) self.assertEqual(resp.status, 204) + # Also test delete_share endpoint leads to bulk unshare without user key + with self.patch_json_dump: + alt_mock_request = self.mock_request + del alt_mock_request.query["user"] + resp = await delete_share_handler(alt_mock_request) + self.assertEqual(resp.status, 204) + async def test_endpoint_delete_container_shares_correct(self): """Test the delete_container_shares endpoint for conformity.""" with self.patch_json_dump: resp = await delete_container_shares_handler(self.mock_request) self.assertEqual(resp.status, 204) + + async def test_endpoint_handle_user_add_token(self): + """Test the handle_user_add_token endpoint for conformity.""" + with self.patch_json_dump: + resp = await handle_user_add_token(self.mock_request) + self.assertEqual(resp.status, 200) + + # Also test when no token is present in query + del self.mock_request.query["token"] + with self.patch_json_dump: + with self.assertRaises(aiohttp.web.HTTPBadRequest): + await handle_user_add_token(self.mock_request) + + async def test_endpoint_handle_user_delete_token(self): + """Test the handle_user_delete_token endpoint for conformity.""" + with self.patch_json_dump: + resp = await handle_user_delete_token(self.mock_request) + self.assertEqual(resp.status, 200) + + async def test_endpoint_handle_user_list_tokens(self): + """Test the handle_user_list_tokens endpoint for conformity.""" + with self.patch_json_dump: + await handle_user_list_tokens(self.mock_request) + self.json_mock.assert_called_once() + + async def test_endpoint_handle_health_check(self): + """Test the handle_health_check endpoint for conformity.""" + with self.patch_json_dump: + await handle_health_check(self.mock_request) + + self.mock_request.app["db_conn"].pool = {} + with self.patch_json_dump: + await handle_health_check(self.mock_request) + + del self.mock_request.app["db_conn"].pool + with self.patch_json_dump: + await handle_health_check(self.mock_request) + + calls = [ + unittest.mock.call({'status': 'Ok'}), + unittest.mock.call({"status": "Degraded", "degraded": ["database"]}) + ] + self.json_mock.assert_has_calls(calls) \ No newline at end of file diff --git a/tests/ui_unit/test_api.py b/tests/ui_unit/test_api.py index f1bf901d7..8a2c25971 100644 --- a/tests/ui_unit/test_api.py +++ b/tests/ui_unit/test_api.py @@ -611,13 +611,15 @@ def setUp(self): """.""" super().setUp() self.mock_request.match_info = { - "project": "test-project", + "project": "test-id-1", "container": "test-container", "object": "test-object", + "object_name": "test-object-name", } self.mock_request.query = { "from_container": "test-container-2", "from_project": "test-project-2", + "project": "test-project", } self.mock_request.query_string = ("&test-query=test-value§",) self.mock_request.remote = ("remote",) @@ -682,3 +684,21 @@ async def test_get_upload_session(self): ) self.session_open_mock.assert_awaited_once() self.sign_mock.assert_awaited_once() + + async def test_get_crypted_upload_session(self): + """Test get crypted upload session.""" + with self.p_get_sess, self.patch_runner_session, self.patch_setd, self.patch_sign: + await swift_browser_ui.ui.api.get_crypted_upload_session( + self.mock_request, + ) + self.session_open_mock.assert_awaited_once() + self.assertEqual(self.sign_mock.await_count, 2) + + async def test_close_upload_session(self): + """Test close upload session.""" + with self.p_get_sess, self.patch_runner_session, self.patch_setd, self.patch_sign: + resp = await swift_browser_ui.ui.api.close_upload_session( + self.mock_request, + ) + self.mock_client.delete.assert_called_once() + self.assertEqual(200, resp.status) \ No newline at end of file From 7971001039510f1789b4e6cd503e81573682ad5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joonatan=20M=C3=A4kinen?= Date: Tue, 28 Mar 2023 20:43:12 +0300 Subject: [PATCH 2/3] Add ui health unit tests --- swift_browser_ui/ui/health.py | 2 +- tests/common/mockups.py | 6 +- tests/ui_unit/test_health.py | 152 ++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 tests/ui_unit/test_health.py diff --git a/swift_browser_ui/ui/health.py b/swift_browser_ui/ui/health.py index bde0babed..9e56b4686 100644 --- a/swift_browser_ui/ui/health.py +++ b/swift_browser_ui/ui/health.py @@ -113,7 +113,7 @@ async def get_upload_runner( _set_error_status(request, services, "swiftui-upload-runner") except Exception as e: request.app["Log"].info(f"Health failed for reason: {e}") - _set_error_status(request, services, "sswiftui-upload-runner") + _set_error_status(request, services, "swiftui-upload-runner") async def handle_health_check(request: aiohttp.web.Request) -> aiohttp.web.Response: diff --git a/tests/common/mockups.py b/tests/common/mockups.py index eaa56102f..ec9e31c96 100644 --- a/tests/common/mockups.py +++ b/tests/common/mockups.py @@ -72,8 +72,8 @@ def setUp(self): "set_origin_address": "https://localhost/login/websso", "has_trust": True, "upload_external_endpoint": "http://test-endpoint:9092/", - "upload_internal_endpoint": "http://test-endpoint:9093/", "oidc_enabled": False, + "upload_internal_endpoint": "http://test-endpoint", } self.patch_setd = unittest.mock.patch( "swift_browser_ui.ui.api.setd", self.setd_mock @@ -114,14 +114,14 @@ def setUp(self): async def citer(_): yield self.mock_iter() - self.mock_client_json = {} + self.mock_client_json = {"status": "Ok"} self.mock_client_text = "" self.mock_client_response = types.SimpleNamespace( **{ "status": 200, "headers": {}, "cookie": {}, - "json": None, + "json": unittest.mock.AsyncMock(return_value=self.mock_client_json), "content": types.SimpleNamespace( **{ "iter_chunked": citer, diff --git a/tests/ui_unit/test_health.py b/tests/ui_unit/test_health.py new file mode 100644 index 000000000..91b321853 --- /dev/null +++ b/tests/ui_unit/test_health.py @@ -0,0 +1,152 @@ +"""Module for testing ``swift_browser_ui.ui.health``.""" + + +import json +import unittest +import types + +import aiohttp.web + +import tests.common.mockups +import swift_browser_ui.ui.health + + +class HealthTestClass(tests.common.mockups.APITestBase): + """Test the Object Browser API.""" + + def setUp(self): + """Set up mocks.""" + super().setUp() + self.mock_services = {} + self.mock_api_params = {} + self.mock_performance = {} + + self.mock_setd = { + "upload_internal_endpoint": "http://test-endpoint", + "sharing_internal_endpoint": "http://test-endpoint", + "request_internal_endpoint": "http://test-endpoint", + } + self.setd = unittest.mock.patch( + "swift_browser_ui.ui.health.setd", self.mock_setd + ) + + async def test_get_x_account_sharing(self): + """Test getting x account sharing.""" + with self.setd: + await swift_browser_ui.ui.health.get_x_account_sharing( + self.mock_services, + self.mock_request, + self.mock_client, + self.mock_api_params, + self.mock_performance, + ) + self.mock_client.get.assert_called_once() + self.assertEqual(self.mock_services["swift-x-account-sharing"], {"status": "Ok"}) + self.assertIn("time", self.mock_performance["swift-x-account-sharing"]) + first_time = self.mock_performance["swift-x-account-sharing"]["time"] + + self.mock_client_response.status = 503 + with self.setd: + await swift_browser_ui.ui.health.get_x_account_sharing( + self.mock_services, + self.mock_request, + self.mock_client, + self.mock_api_params, + self.mock_performance, + ) + self.assertEqual(self.mock_services["swift-x-account-sharing"], {"status": "Down"}) + self.assertNotEqual(first_time, self.mock_performance["swift-x-account-sharing"]["time"]) + + async def test_get_swift_sharing(self): + """Test getting swift sharing.""" + with self.setd: + await swift_browser_ui.ui.health.get_swift_sharing( + self.mock_services, + self.mock_request, + self.mock_client, + self.mock_api_params, + self.mock_performance, + ) + self.mock_client.get.assert_called_once() + self.assertEqual(self.mock_services["swift-sharing-request"], {"status": "Ok"}) + self.assertIn("time", self.mock_performance["swift-sharing-request"]) + first_time = self.mock_performance["swift-sharing-request"]["time"] + + self.mock_client_response.status = 503 + with self.setd: + await swift_browser_ui.ui.health.get_swift_sharing( + self.mock_services, + self.mock_request, + self.mock_client, + self.mock_api_params, + self.mock_performance, + ) + self.assertEqual(self.mock_services["swift-sharing-request"], {"status": "Down"}) + self.assertNotEqual(first_time, self.mock_performance["swift-sharing-request"]["time"]) + + async def test_get_upload_runner(self): + """Test getting upload runner.""" + with self.setd: + await swift_browser_ui.ui.health.get_upload_runner( + self.mock_services, + self.mock_request, + self.mock_client, + self.mock_api_params, + self.mock_performance, + ) + self.mock_client.get.assert_called_once() + self.assertEqual(self.mock_services["swiftui-upload-runner"], {"status": "Ok"}) + self.assertIn("time", self.mock_performance["swiftui-upload-runner"]) + first_time = self.mock_performance["swiftui-upload-runner"]["time"] + + self.mock_client_response.status = 503 + with self.setd: + await swift_browser_ui.ui.health.get_upload_runner( + self.mock_services, + self.mock_request, + self.mock_client, + self.mock_api_params, + self.mock_performance, + ) + self.assertEqual(self.mock_services["swiftui-upload-runner"], {"status": "Down"}) + self.assertNotEqual(first_time, self.mock_performance["swiftui-upload-runner"]["time"]) + + async def test_some_exception(self): + """Test that an exception happens when getting one of the service statuses.""" + self.mock_client_response.json = None + with self.setd: + await swift_browser_ui.ui.health.get_upload_runner( + self.mock_services, + self.mock_request, + self.mock_client, + self.mock_api_params, + self.mock_performance, + ) + self.assertEqual(self.mock_services["swiftui-upload-runner"], {"status": "Error"}) + + async def test_nonexistant_service(self): + """Test get_upload_runner when upload_internal_endpoint is not assigned.""" + self.mock_setd["upload_internal_endpoint"] = None + with self.setd: + await swift_browser_ui.ui.health.get_upload_runner( + self.mock_services, + self.mock_request, + self.mock_client, + self.mock_api_params, + self.mock_performance, + ) + self.assertEqual(self.mock_services["swiftui-upload-runner"], {"status": "Nonexistent"}) + + async def test_handle_health_check(self): + """Test handling health check.""" + with self.setd, self.p_json_resp: + await swift_browser_ui.ui.health.handle_health_check(self.mock_request) + self.aiohttp_json_response_mock.assert_called() + status = self.aiohttp_json_response_mock.call_args_list[0][0][0]["status"] + self.assertEqual(status, "Ok") + + self.mock_client_response.status = 503 + with self.setd, self.p_json_resp: + await swift_browser_ui.ui.health.handle_health_check(self.mock_request) + status = self.aiohttp_json_response_mock.call_args_list[1][0][0]["status"] + self.assertEqual(status, "Partially down") From aecab507ede73b3a8348870c0e603296e79dadbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joonatan=20M=C3=A4kinen?= Date: Thu, 30 Mar 2023 19:03:06 +0300 Subject: [PATCH 3/3] Add unit tests for upload module --- tests/common/mockups.py | 2 +- tests/request/test_api.py | 13 ++-- tests/sharing/test_api.py | 14 ++-- tests/ui_unit/test_api.py | 2 +- tests/ui_unit/test_health.py | 28 ++++--- tests/upload/test_upload.py | 137 +++++++++++++++++++++++++++++++++++ 6 files changed, 167 insertions(+), 29 deletions(-) create mode 100644 tests/upload/test_upload.py diff --git a/tests/common/mockups.py b/tests/common/mockups.py index ec9e31c96..861ed38f3 100644 --- a/tests/common/mockups.py +++ b/tests/common/mockups.py @@ -39,7 +39,7 @@ def setUp(self): "token": "test-token-1", "endpoint": "https://test-endpoint-1/v1/AUTH_test-id-1", "tainted": False, - "runner": "test-runner" + "runner": "test-runner", }, } self.aiohttp_session_get_session_mock = unittest.mock.AsyncMock() diff --git a/tests/request/test_api.py b/tests/request/test_api.py index 7516848d0..bc3f8f8f5 100644 --- a/tests/request/test_api.py +++ b/tests/request/test_api.py @@ -2,7 +2,7 @@ import unittest -from unittest import mock +import unittest.mock from types import SimpleNamespace import aiohttp @@ -17,7 +17,7 @@ handle_user_add_token, handle_user_delete_token, handle_user_list_tokens, - handle_health_check + handle_health_check, ) @@ -43,10 +43,7 @@ def setUp(self): } ) }, - "query": { - "owner": "AUTH_otherexample", - "token": "user_token" - }, + "query": {"owner": "AUTH_otherexample", "token": "user_token"}, "match_info": { "container": "test", "user": "test", @@ -130,7 +127,7 @@ async def test_endpoint_handle_health_check(self): await handle_health_check(self.mock_request) calls = [ - unittest.mock.call({'status': 'Ok'}), - unittest.mock.call({"status": "Degraded", "degraded": ["database"]}) + unittest.mock.call({"status": "Ok"}), + unittest.mock.call({"status": "Degraded", "degraded": ["database"]}), ] self.json_mock.assert_has_calls(calls) diff --git a/tests/sharing/test_api.py b/tests/sharing/test_api.py index b93bd8c5c..8ce6d578b 100644 --- a/tests/sharing/test_api.py +++ b/tests/sharing/test_api.py @@ -4,7 +4,7 @@ from types import SimpleNamespace import unittest -from unittest import mock +import unittest.mock import aiohttp.web @@ -20,7 +20,7 @@ handle_user_add_token, handle_user_delete_token, handle_user_list_tokens, - handle_health_check + handle_health_check, ) @@ -58,8 +58,8 @@ def setUp(self): "token": "user_token", }, "match_info": { - "container": "test", - "user": "test", + "container": "test", + "user": "test", "owner": "test", "project": "test", "id": "test", @@ -167,7 +167,7 @@ async def test_endpoint_handle_health_check(self): await handle_health_check(self.mock_request) calls = [ - unittest.mock.call({'status': 'Ok'}), - unittest.mock.call({"status": "Degraded", "degraded": ["database"]}) + unittest.mock.call({"status": "Ok"}), + unittest.mock.call({"status": "Degraded", "degraded": ["database"]}), ] - self.json_mock.assert_has_calls(calls) \ No newline at end of file + self.json_mock.assert_has_calls(calls) diff --git a/tests/ui_unit/test_api.py b/tests/ui_unit/test_api.py index 8a2c25971..00901b644 100644 --- a/tests/ui_unit/test_api.py +++ b/tests/ui_unit/test_api.py @@ -701,4 +701,4 @@ async def test_close_upload_session(self): self.mock_request, ) self.mock_client.delete.assert_called_once() - self.assertEqual(200, resp.status) \ No newline at end of file + self.assertEqual(200, resp.status) diff --git a/tests/ui_unit/test_health.py b/tests/ui_unit/test_health.py index 91b321853..8131014f2 100644 --- a/tests/ui_unit/test_health.py +++ b/tests/ui_unit/test_health.py @@ -1,11 +1,7 @@ """Module for testing ``swift_browser_ui.ui.health``.""" -import json import unittest -import types - -import aiohttp.web import tests.common.mockups import swift_browser_ui.ui.health @@ -26,9 +22,7 @@ def setUp(self): "sharing_internal_endpoint": "http://test-endpoint", "request_internal_endpoint": "http://test-endpoint", } - self.setd = unittest.mock.patch( - "swift_browser_ui.ui.health.setd", self.mock_setd - ) + self.setd = unittest.mock.patch("swift_browser_ui.ui.health.setd", self.mock_setd) async def test_get_x_account_sharing(self): """Test getting x account sharing.""" @@ -54,8 +48,12 @@ async def test_get_x_account_sharing(self): self.mock_api_params, self.mock_performance, ) - self.assertEqual(self.mock_services["swift-x-account-sharing"], {"status": "Down"}) - self.assertNotEqual(first_time, self.mock_performance["swift-x-account-sharing"]["time"]) + self.assertEqual( + self.mock_services["swift-x-account-sharing"], {"status": "Down"} + ) + self.assertNotEqual( + first_time, self.mock_performance["swift-x-account-sharing"]["time"] + ) async def test_get_swift_sharing(self): """Test getting swift sharing.""" @@ -82,7 +80,9 @@ async def test_get_swift_sharing(self): self.mock_performance, ) self.assertEqual(self.mock_services["swift-sharing-request"], {"status": "Down"}) - self.assertNotEqual(first_time, self.mock_performance["swift-sharing-request"]["time"]) + self.assertNotEqual( + first_time, self.mock_performance["swift-sharing-request"]["time"] + ) async def test_get_upload_runner(self): """Test getting upload runner.""" @@ -109,7 +109,9 @@ async def test_get_upload_runner(self): self.mock_performance, ) self.assertEqual(self.mock_services["swiftui-upload-runner"], {"status": "Down"}) - self.assertNotEqual(first_time, self.mock_performance["swiftui-upload-runner"]["time"]) + self.assertNotEqual( + first_time, self.mock_performance["swiftui-upload-runner"]["time"] + ) async def test_some_exception(self): """Test that an exception happens when getting one of the service statuses.""" @@ -135,7 +137,9 @@ async def test_nonexistant_service(self): self.mock_api_params, self.mock_performance, ) - self.assertEqual(self.mock_services["swiftui-upload-runner"], {"status": "Nonexistent"}) + self.assertEqual( + self.mock_services["swiftui-upload-runner"], {"status": "Nonexistent"} + ) async def test_handle_health_check(self): """Test handling health check.""" diff --git a/tests/upload/test_upload.py b/tests/upload/test_upload.py new file mode 100644 index 000000000..5766722c3 --- /dev/null +++ b/tests/upload/test_upload.py @@ -0,0 +1,137 @@ +"""Unit tests for swift_browser_ui.upload.upload module.""" + +import unittest.mock + +import aiohttp.web + +from swift_browser_ui.upload.upload import ResumableFileUploadProxy +import tests.common.mockups + + +class UploadTestClass(tests.common.mockups.APITestBase): + """Test class for swift_browser_ui.upload.upload functions.""" + + def setUp(self): + """Set up mocks.""" + super().setUp() + self.mock_session = { + "endpoint": "https://test-endpoint-0/v1/AUTH_test-id", + "token": "test-token", + } + self.mock_query = { + "resumableChunkSize": 0, + "resumableTotalSize": 9999999999, + "resumableChunkNumber": 10, + "resumableTotalChunks": 10, + "resumableType": "", + "resumableIdentifier": "", + "resumableFilename": "", + "resumableRelativePath": "", + } + self.file_upload_proxy = ResumableFileUploadProxy( + self.mock_session, + self.mock_query, + self.mock_request.match_info, + self.mock_client, + ) + + async def test_create_container(self): + """Test creating a container for an upload.""" + self.mock_client_response.status = 200 + with self.assertRaises(aiohttp.web.HTTPForbidden): + await self.file_upload_proxy.a_create_container() + self.mock_client.head.assert_called_once() + self.mock_client.put.assert_called_once() + self.mock_client.head.reset_mock() + self.mock_client.put.reset_mock() + + self.mock_client_response.status = 201 + await self.file_upload_proxy.a_create_container() + self.assertEqual(self.mock_client.head.call_count, 2) + self.assertEqual(self.mock_client.put.call_count, 2) + + async def test_check_container(self): + """Test checking if container is allowed.""" + with self.assertRaises(aiohttp.web.HTTPBadRequest): + await self.file_upload_proxy.a_check_container() + self.mock_client.head.assert_called_once() + self.mock_client.head.reset_mock() + + self.mock_client_response.status = 201 + match_info = { + "project": "AUTH_test-id", + "container": "test-container", + } + new_proxy = ResumableFileUploadProxy( + self.mock_session, + self.mock_query, + match_info, + self.mock_client, + ) + await new_proxy.a_check_container() + self.assertEqual(self.mock_client.head.call_count, 3) + + async def test_check_segment(self): + """Test checking existence of a segment.""" + resp = await self.file_upload_proxy.a_check_segment(1) + self.mock_client.head.assert_called_once() + self.mock_client.head.reset_mock() + self.assertEqual(resp.status, 200) + + self.mock_client_response.status = 204 + resp = await self.file_upload_proxy.a_check_segment(1) + self.mock_client.head.assert_called_once() + self.assertEqual(resp.status, 204) + + async def test_add_manifest(self): + """Test adding manifest file.""" + with self.assertRaises(aiohttp.web.HTTPBadRequest): + await self.file_upload_proxy.a_add_manifest() + self.mock_client.put.assert_called_once() + self.mock_client.put.reset_mock() + + self.mock_client_response.status = 201 + await self.file_upload_proxy.a_add_manifest() + self.mock_client.put.assert_called_once() + + async def test_add_chunk(self): + """Test adding chunk.""" + self.mock_chunk_reader = unittest.mock.Mock() + self.file_upload_proxy.upload_file = unittest.mock.AsyncMock() + self.patch_coro_upload = unittest.mock.patch( + "swift_browser_ui.upload.upload.ResumableFileUploadProxy.upload_file", + self.file_upload_proxy.upload_file, + ) + + self.file_upload_proxy.done_chunks = {9} + resp = await self.file_upload_proxy.a_add_chunk( + self.mock_query, self.mock_chunk_reader + ) + self.assertEqual(resp.status, 200) + + self.file_upload_proxy.done_chunks = {} + resp = await self.file_upload_proxy.a_add_chunk( + self.mock_query, self.mock_chunk_reader + ) + self.file_upload_proxy.upload_file.assert_awaited_once() + self.assertEqual(resp.status, 201) + + async def test_upload_file(self): + """Test uploading non-segmented file.""" + self.file_upload_proxy.segmented = False + await self.file_upload_proxy.upload_file() + self.mock_client.put.assert_called_once() + self.mock_client_response.status = 408 + with self.assertRaises(aiohttp.web.HTTPRequestTimeout): + await self.file_upload_proxy.upload_file() + self.mock_client_response.status = 411 + with self.assertRaises(aiohttp.web.HTTPLengthRequired): + await self.file_upload_proxy.upload_file() + self.mock_client_response.status = 422 + with self.assertRaises(aiohttp.web.HTTPUnprocessableEntity): + await self.file_upload_proxy.upload_file() + + async def test_wait_for_chunk(self): + """Test the method doesn't get stuck in an infinite loop.""" + self.file_upload_proxy.done_chunks = {1} + await self.file_upload_proxy.a_wait_for_chunk(1)