proxy.py/tests/core/test_connection.py

120 lines
4.5 KiB
Python

# -*- 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
import socket
import ssl
from unittest import mock
from typing import Optional, Union
from proxy.core.connection import tcpConnectionTypes, TcpConnectionUninitializedException
from proxy.core.connection import TcpServerConnection, TcpConnection, TcpClientConnection
from proxy.common.constants import DEFAULT_IPV6_HOSTNAME, DEFAULT_PORT, DEFAULT_IPV4_HOSTNAME
class TestTcpConnection(unittest.TestCase):
class TcpConnectionToTest(TcpConnection):
def __init__(self, conn: Optional[Union[ssl.SSLSocket, socket.socket]] = None,
tag: int = tcpConnectionTypes.CLIENT) -> None:
super().__init__(tag)
self._conn = conn
@property
def connection(self) -> Union[ssl.SSLSocket, socket.socket]:
if self._conn is None:
raise TcpConnectionUninitializedException()
return self._conn
def testThrowsKeyErrorIfNoConn(self) -> None:
self.conn = TestTcpConnection.TcpConnectionToTest()
with self.assertRaises(TcpConnectionUninitializedException):
self.conn.send(b'dummy')
with self.assertRaises(TcpConnectionUninitializedException):
self.conn.recv()
with self.assertRaises(TcpConnectionUninitializedException):
self.conn.close()
def testClosesIfNotClosed(self) -> None:
_conn = mock.MagicMock()
self.conn = TestTcpConnection.TcpConnectionToTest(_conn)
self.conn.close()
_conn.close.assert_called()
self.assertTrue(self.conn.closed)
def testNoOpIfAlreadyClosed(self) -> None:
_conn = mock.MagicMock()
self.conn = TestTcpConnection.TcpConnectionToTest(_conn)
self.conn.closed = True
self.conn.close()
_conn.close.assert_not_called()
self.assertTrue(self.conn.closed)
def testFlushReturnsIfNoBuffer(self) -> None:
_conn = mock.MagicMock()
self.conn = TestTcpConnection.TcpConnectionToTest(_conn)
self.conn.flush()
self.assertTrue(not _conn.send.called)
@mock.patch('socket.socket')
def testTcpServerEstablishesIPv6Connection(
self, mock_socket: mock.Mock) -> None:
conn = TcpServerConnection(
str(DEFAULT_IPV6_HOSTNAME), DEFAULT_PORT)
conn.connect()
mock_socket.assert_called()
mock_socket.return_value.connect.assert_called_with(
(str(DEFAULT_IPV6_HOSTNAME), DEFAULT_PORT, 0, 0))
@mock.patch('proxy.core.connection.new_socket_connection')
def testTcpServerIgnoresDoubleConnectSilently(
self,
mock_new_socket_connection: mock.Mock) -> None:
conn = TcpServerConnection(
str(DEFAULT_IPV6_HOSTNAME), DEFAULT_PORT)
conn.connect()
conn.connect()
mock_new_socket_connection.assert_called_once()
@mock.patch('socket.socket')
def testTcpServerEstablishesIPv4Connection(
self, mock_socket: mock.Mock) -> None:
conn = TcpServerConnection(
str(DEFAULT_IPV4_HOSTNAME), DEFAULT_PORT)
conn.connect()
mock_socket.assert_called()
mock_socket.return_value.connect.assert_called_with(
(str(DEFAULT_IPV4_HOSTNAME), DEFAULT_PORT))
@mock.patch('proxy.core.connection.new_socket_connection')
def testTcpServerConnectionProperty(
self,
mock_new_socket_connection: mock.Mock) -> None:
conn = TcpServerConnection(
str(DEFAULT_IPV6_HOSTNAME), DEFAULT_PORT)
conn.connect()
self.assertEqual(
conn.connection,
mock_new_socket_connection.return_value)
def testTcpServerRaisesTcpConnectionUninitializedException(self) -> None:
conn = TcpServerConnection(
str(DEFAULT_IPV6_HOSTNAME), DEFAULT_PORT)
with self.assertRaises(TcpConnectionUninitializedException):
_ = conn.connection
def testTcpClientRaisesTcpConnectionUninitializedException(self) -> None:
_conn = mock.MagicMock()
_addr = mock.MagicMock()
conn = TcpClientConnection(_conn, _addr)
conn._conn = None
with self.assertRaises(TcpConnectionUninitializedException):
_ = conn.connection