From e38f1a8feecf0f62669c29a490cff7a895866173 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 10 Nov 2021 21:40:51 +0530 Subject: [PATCH] Test cov (#721) * nocover for abstract classes * Add event manager test * Assert call args * Sponsored by `Jaxl Innovations Private Limited` --- README.md | 12 ++++----- proxy/core/base/tcp_server.py | 2 +- proxy/dashboard/plugin.py | 8 +++--- proxy/http/websocket/client.py | 4 +-- proxy/plugin/cloudflare_dns.py | 6 +++-- tests/core/test_event_manager.py | 46 ++++++++++++++++++++++++++++++++ 6 files changed, 62 insertions(+), 16 deletions(-) create mode 100644 tests/core/test_event_manager.py diff --git a/README.md b/README.md index 9fdb7f8980..4825291cf0 100644 --- a/README.md +++ b/README.md @@ -4,24 +4,22 @@ [![Docker Pulls](https://img.shields.io/docker/pulls/abhinavsingh/proxy.py?style=for-the-badge&color=darkgreen)](https://hub.docker.com/r/abhinavsingh/proxy.py) [![No Dependencies](https://img.shields.io/static/v1?label=dependencies&message=0&style=for-the-badge&color=darkgreen)](https://github.com/abhinavsingh/proxy.py) [![Gitter](https://img.shields.io/gitter/room/abhinavsingh/proxy.py?style=for-the-badge&color=darkgreen)](https://gitter.im/proxy-py/community) -[![License](https://img.shields.io/github/license/abhinavsingh/proxy.py?style=for-the-badge&color=darkgreen)](https://opensource.org/licenses/BSD-3-Clause) +[![License](https://img.shields.io/github/license/abhinavsingh/proxy.py?style=for-the-badge&color=darkgreen)](https://github.com/abhinavsingh/proxy.py/blob/develop/LICENSE) [![Tested With MacOS, Ubuntu, Windows, Android, Android Emulator, iOS, iOS Simulator](https://img.shields.io/static/v1?label=tested%20with&message=mac%20OS%20%F0%9F%92%BB%20%7C%20Ubuntu%20%F0%9F%96%A5%20%7C%20Windows%20%F0%9F%92%BB&color=darkgreen&style=for-the-badge)](https://abhinavsingh.com/proxy-py-a-lightweight-single-file-http-proxy-server-in-python/) [![Android, Android Emulator](https://img.shields.io/static/v1?label=tested%20with&message=Android%20%F0%9F%93%B1%20%7C%20Android%20Emulator%20%F0%9F%93%B1&color=darkgreen&style=for-the-badge)](https://abhinavsingh.com/proxy-py-a-lightweight-single-file-http-proxy-server-in-python/) [![iOS, iOS Simulator](https://img.shields.io/static/v1?label=tested%20with&message=iOS%20%F0%9F%93%B1%20%7C%20iOS%20Simulator%20%F0%9F%93%B1&color=darkgreen&style=for-the-badge)](https://abhinavsingh.com/proxy-py-a-lightweight-single-file-http-proxy-server-in-python/) - - [![lib](https://github.com/abhinavsingh/proxy.py/actions/workflows/test-library.yml/badge.svg)](https://github.com/abhinavsingh/proxy.py/actions/workflows/test-library.yml) [![docker](https://github.com/abhinavsingh/proxy.py/actions/workflows/test-docker.yml/badge.svg)](https://github.com/abhinavsingh/proxy.py/actions/workflows/test-docker.yml) [![dashboard](https://github.com/abhinavsingh/proxy.py/actions/workflows/test-dashboard.yml/badge.svg)](https://github.com/abhinavsingh/proxy.py/actions/workflows/test-dashboard.yml) [![brew](https://github.com/abhinavsingh/proxy.py/actions/workflows/test-brew.yml/badge.svg)](https://github.com/abhinavsingh/proxy.py/actions/workflows/test-brew.yml) [![CodeQL](https://github.com/abhinavsingh/proxy.py/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/abhinavsingh/proxy.py/actions/workflows/codeql-analysis.yml) +[![Contributions Welcome](https://img.shields.io/static/v1?label=Contributions&message=Welcome%20%F0%9F%91%8D&color=darkgreen)](https://github.com/abhinavsingh/proxy.py/issues) +[![Need Help](https://img.shields.io/static/v1?label=Need%20Help%3F&message=Ask&color=darkgreen)](https://twitter.com/imoracle) +[![Sponsored by Jaxl Innovations Private Limited](https://img.shields.io/static/v1?label=Sponsored%20By&message=Jaxl%20Innovations%20Private%20Limited&color=darkgreen)](https://github.com/jaxl-innovations-private-limited) + [![pypi version](https://img.shields.io/pypi/v/proxy.py)](https://pypi.org/project/proxy.py/) [![Python 3.x](https://img.shields.io/static/v1?label=Python&message=3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9%20%7C%203.10&color=blue)](https://www.python.org/) [![Checked with mypy](https://img.shields.io/static/v1?label=MyPy&message=checked&color=blue)](http://mypy-lang.org/) diff --git a/proxy/core/base/tcp_server.py b/proxy/core/base/tcp_server.py index 261a493fe5..fa1ca9a14b 100644 --- a/proxy/core/base/tcp_server.py +++ b/proxy/core/base/tcp_server.py @@ -45,7 +45,7 @@ class BaseTcpServerHandler(Work): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.must_flush_before_shutdown = False - if self.flags.unix_socket_path: + if self.flags.unix_socket_path: # pragma: no cover logger.debug( 'Connection accepted from {0}'.format(self.work.address), ) diff --git a/proxy/dashboard/plugin.py b/proxy/dashboard/plugin.py index 8e36a600fc..86032c69e0 100644 --- a/proxy/dashboard/plugin.py +++ b/proxy/dashboard/plugin.py @@ -35,20 +35,20 @@ def __init__( @abstractmethod def methods(self) -> List[str]: """Return list of methods that this plugin will handle.""" - pass + pass # pragma: no cover def connected(self) -> None: """Invoked when client websocket handshake finishes.""" - pass + pass # pragma: no cover @abstractmethod def handle_message(self, message: Dict[str, Any]) -> None: """Handle messages for registered methods.""" - pass + pass # pragma: no cover def disconnected(self) -> None: """Invoked when client websocket connection gets closed.""" - pass + pass # pragma: no cover def reply(self, data: Dict[str, Any]) -> None: self.client.queue( diff --git a/proxy/http/websocket/client.py b/proxy/http/websocket/client.py index 902b891914..528790d12c 100644 --- a/proxy/http/websocket/client.py +++ b/proxy/http/websocket/client.py @@ -74,10 +74,10 @@ def upgrade(self) -> None: assert WebsocketFrame.key_to_accept(key) == accept def ping(self, data: Optional[bytes] = None) -> None: - pass + pass # pragma: no cover def pong(self, data: Optional[bytes] = None) -> None: - pass + pass # pragma: no cover def shutdown(self, _data: Optional[bytes] = None) -> None: """Closes connection with the server.""" diff --git a/proxy/plugin/cloudflare_dns.py b/proxy/plugin/cloudflare_dns.py index da188563e6..6cf1e15688 100644 --- a/proxy/plugin/cloudflare_dns.py +++ b/proxy/plugin/cloudflare_dns.py @@ -12,7 +12,7 @@ try: import httpx -except ImportError: +except ImportError: # pragma: no cover pass from typing import Optional, Tuple @@ -75,7 +75,9 @@ def resolve_dns(self, host: str, port: int) -> Tuple[Optional[str], Optional[Tup return answers[0]['data'], None except Exception as e: logger.info( - 'Unable to resolve DNS-over-HTTPS for host {0} : {1}'.format(host, str(e)), + 'Unable to resolve DNS-over-HTTPS for host {0} : {1}'.format( + host, str(e), + ), ) return None, None diff --git a/tests/core/test_event_manager.py b/tests/core/test_event_manager.py new file mode 100644 index 0000000000..5f532a95fe --- /dev/null +++ b/tests/core/test_event_manager.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +""" + proxy.py + ~~~~~~~~ + ⚡⚡⚡ Fast, Lightweight, Pluggable, TLS interception capable proxy server focused on + Network monitoring, controls & Application development, testing, debugging. + + :copyright: (c) 2013-present by Abhinav Singh and contributors. + :license: BSD, see LICENSE for more details. +""" +import unittest + +from unittest import mock + +from proxy.core.event import EventManager + + +class TestEventManager(unittest.TestCase): + + @mock.patch('proxy.core.event.manager.EventQueue') + @mock.patch('proxy.core.event.manager.EventDispatcher') + @mock.patch('proxy.core.event.manager.multiprocessing.Queue') + @mock.patch('proxy.core.event.manager.threading.Event') + @mock.patch('proxy.core.event.manager.threading.Thread') + def test_setup_and_teardown( + self, + mock_thread: mock.Mock, + mock_event: mock.Mock, + mock_queue: mock.Mock, + mock_dispatcher: mock.Mock, + mock_event_queue: mock.Mock, + ) -> None: + with EventManager() as _: + mock_queue.assert_called_once() + mock_event.assert_called_once() + mock_thread.assert_called_once_with( + target=mock_dispatcher.return_value.run, + ) + mock_thread.return_value.start.assert_called_once() + mock_event_queue.assert_called_once_with(mock_queue.return_value) + mock_dispatcher.assert_called_once_with( + shutdown=mock_event.return_value, + event_queue=mock_event_queue.return_value, + ) + mock_event.return_value.set.assert_called_once() + mock_thread.return_value.join.assert_called_once()