An attempt at adding UDP support to aiosocks. Untested due to lack of server support.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

151 lines
5.5 KiB

  1. import unittest
  2. import asyncio
  3. import aiosocks
  4. import aiohttp
  5. import pytest
  6. from unittest import mock
  7. from aiohttp.client_reqrep import ClientRequest
  8. from aiosocks.connector import SocksConnector, proxy_connector
  9. from .helpers import fake_coroutine
  10. class TestSocksConnector(unittest.TestCase):
  11. def setUp(self):
  12. self.loop = asyncio.new_event_loop()
  13. asyncio.set_event_loop(None)
  14. def tearDown(self):
  15. self.loop.close()
  16. def test_properties(self):
  17. addr = aiosocks.Socks4Addr('localhost')
  18. auth = aiosocks.Socks4Auth('login')
  19. conn = SocksConnector(addr, auth, loop=self.loop)
  20. self.assertIs(conn.proxy, addr)
  21. self.assertIs(conn.proxy_auth, auth)
  22. @mock.patch('aiosocks.connector.create_connection')
  23. def test_connect_proxy_ip(self, cr_conn_mock):
  24. tr, proto = mock.Mock(name='transport'), mock.Mock(name='protocol')
  25. cr_conn_mock.side_effect = \
  26. fake_coroutine((tr, proto)).side_effect
  27. loop_mock = mock.Mock()
  28. req = ClientRequest('GET', 'http://python.org', loop=self.loop)
  29. connector = SocksConnector(aiosocks.Socks5Addr('127.0.0.1'),
  30. None, loop=loop_mock)
  31. loop_mock.getaddrinfo = fake_coroutine([mock.MagicMock()])
  32. conn = self.loop.run_until_complete(connector.connect(req))
  33. self.assertTrue(loop_mock.getaddrinfo.is_called)
  34. self.assertIs(conn._transport, tr)
  35. conn.close()
  36. @mock.patch('aiosocks.connector.create_connection')
  37. def test_connect_proxy_domain(self, cr_conn_mock):
  38. tr, proto = mock.Mock(name='transport'), mock.Mock(name='protocol')
  39. cr_conn_mock.side_effect = \
  40. fake_coroutine((tr, proto)).side_effect
  41. loop_mock = mock.Mock()
  42. req = ClientRequest('GET', 'http://python.org', loop=self.loop)
  43. connector = SocksConnector(aiosocks.Socks5Addr('proxy.example'),
  44. None, loop=loop_mock)
  45. connector._resolve_host = fake_coroutine([mock.MagicMock()])
  46. conn = self.loop.run_until_complete(connector.connect(req))
  47. self.assertTrue(connector._resolve_host.is_called)
  48. self.assertEqual(connector._resolve_host.call_count, 1)
  49. self.assertIs(conn._transport, tr)
  50. conn.close()
  51. @mock.patch('aiosocks.connector.create_connection')
  52. def test_connect_remote_resolve(self, cr_conn_mock):
  53. tr, proto = mock.Mock(name='transport'), mock.Mock(name='protocol')
  54. cr_conn_mock.side_effect = \
  55. fake_coroutine((tr, proto)).side_effect
  56. req = ClientRequest('GET', 'http://python.org', loop=self.loop)
  57. connector = SocksConnector(aiosocks.Socks5Addr('127.0.0.1'),
  58. None, loop=self.loop, remote_resolve=True)
  59. connector._resolve_host = fake_coroutine([mock.MagicMock()])
  60. conn = self.loop.run_until_complete(connector.connect(req))
  61. self.assertEqual(connector._resolve_host.call_count, 1)
  62. conn.close()
  63. @mock.patch('aiosocks.connector.create_connection')
  64. def test_connect_locale_resolve(self, cr_conn_mock):
  65. tr, proto = mock.Mock(name='transport'), mock.Mock(name='protocol')
  66. cr_conn_mock.side_effect = \
  67. fake_coroutine((tr, proto)).side_effect
  68. req = ClientRequest('GET', 'http://python.org', loop=self.loop)
  69. connector = SocksConnector(aiosocks.Socks5Addr('proxy.example'),
  70. None, loop=self.loop, remote_resolve=False)
  71. connector._resolve_host = fake_coroutine([mock.MagicMock()])
  72. conn = self.loop.run_until_complete(connector.connect(req))
  73. self.assertTrue(connector._resolve_host.is_called)
  74. self.assertEqual(connector._resolve_host.call_count, 2)
  75. conn.close()
  76. @mock.patch('aiosocks.connector.create_connection')
  77. def test_proxy_connect_fail(self, cr_conn_mock):
  78. loop_mock = mock.Mock()
  79. cr_conn_mock.side_effect = \
  80. fake_coroutine(aiosocks.SocksConnectionError()).side_effect
  81. req = ClientRequest('GET', 'http://python.org', loop=self.loop)
  82. connector = SocksConnector(aiosocks.Socks5Addr('127.0.0.1'),
  83. None, loop=loop_mock)
  84. loop_mock.getaddrinfo = fake_coroutine([mock.MagicMock()])
  85. with self.assertRaises(aiohttp.ProxyConnectionError):
  86. self.loop.run_until_complete(connector.connect(req))
  87. @mock.patch('aiosocks.connector.create_connection')
  88. def test_proxy_negotiate_fail(self, cr_conn_mock):
  89. loop_mock = mock.Mock()
  90. cr_conn_mock.side_effect = \
  91. fake_coroutine(aiosocks.SocksError()).side_effect
  92. req = ClientRequest('GET', 'http://python.org', loop=self.loop)
  93. connector = SocksConnector(aiosocks.Socks5Addr('127.0.0.1'),
  94. None, loop=loop_mock)
  95. loop_mock.getaddrinfo = fake_coroutine([mock.MagicMock()])
  96. with self.assertRaises(aiosocks.SocksError):
  97. self.loop.run_until_complete(connector.connect(req))
  98. def test_proxy_connector():
  99. socks4_addr = aiosocks.Socks4Addr('h')
  100. socks5_addr = aiosocks.Socks5Addr('h')
  101. http_addr = aiosocks.HttpProxyAddr('http://proxy')
  102. loop = asyncio.new_event_loop()
  103. assert isinstance(proxy_connector(socks4_addr, loop=loop), SocksConnector)
  104. assert isinstance(proxy_connector(socks5_addr, loop=loop), SocksConnector)
  105. assert isinstance(proxy_connector(http_addr, loop=loop),
  106. aiohttp.ProxyConnector)
  107. with pytest.raises(ValueError):
  108. proxy_connector(None)