File: connect.py

package info (click to toggle)
python-stem 1.2.2-1.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 4,568 kB
  • ctags: 2,036
  • sloc: python: 20,108; makefile: 127; sh: 3
file content (141 lines) | stat: -rw-r--r-- 6,708 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
"""
Unit tests for the stem.connection.connect function.
"""

import StringIO
import unittest

from mock import Mock, patch

import stem
import stem.connection
import stem.socket


class TestConnect(unittest.TestCase):
  @patch('sys.stdout', new_callable = StringIO.StringIO)
  @patch('stem.util.system.is_running')
  @patch('os.path.exists', Mock(return_value = True))
  @patch('stem.socket.ControlSocketFile', Mock(side_effect = stem.SocketError('failed')))
  @patch('stem.socket.ControlPort', Mock(side_effect = stem.SocketError('failed')))
  @patch('stem.connection._connect_auth', Mock())
  def test_failue_with_the_default_endpoint(self, is_running_mock, stdout_mock):
    is_running_mock.return_value = False
    self._assert_connect_fails_with({}, stdout_mock, "Unable to connect to tor. Are you sure it's running?")

    is_running_mock.return_value = True
    self._assert_connect_fails_with({}, stdout_mock, "Unable to connect to tor. Maybe it's running without a ControlPort?")

  @patch('sys.stdout', new_callable = StringIO.StringIO)
  @patch('os.path.exists')
  @patch('stem.util.system.is_running', Mock(return_value = True))
  @patch('stem.socket.ControlSocketFile', Mock(side_effect = stem.SocketError('failed')))
  @patch('stem.socket.ControlPort', Mock(side_effect = stem.SocketError('failed')))
  @patch('stem.connection._connect_auth', Mock())
  def test_failure_with_a_custom_endpoint(self, path_exists_mock, stdout_mock):
    path_exists_mock.return_value = True
    self._assert_connect_fails_with({'control_port': ('127.0.0.1', 80), 'control_socket': None}, stdout_mock, "Unable to connect to 127.0.0.1:80: failed")
    self._assert_connect_fails_with({'control_port': None, 'control_socket': '/tmp/my_socket'}, stdout_mock, "Unable to connect to '/tmp/my_socket': failed")

    path_exists_mock.return_value = False
    self._assert_connect_fails_with({'control_port': ('127.0.0.1', 80), 'control_socket': None}, stdout_mock, "Unable to connect to 127.0.0.1:80: failed")
    self._assert_connect_fails_with({'control_port': None, 'control_socket': '/tmp/my_socket'}, stdout_mock, "The socket file you specified (/tmp/my_socket) doesn't exist")

  @patch('stem.socket.ControlPort')
  @patch('os.path.exists', Mock(return_value = False))
  @patch('stem.connection._connect_auth', Mock())
  def test_getting_a_control_port(self, port_mock):
    stem.connection.connect()
    port_mock.assert_called_once_with('127.0.0.1', 9051)
    port_mock.reset_mock()

    stem.connection.connect(control_port = ('255.0.0.10', 80), control_socket = None)
    port_mock.assert_called_once_with('255.0.0.10', 80)

  @patch('stem.socket.ControlSocketFile')
  @patch('os.path.exists', Mock(return_value = True))
  @patch('stem.connection._connect_auth', Mock())
  def test_getting_a_control_socket(self, socket_mock):
    stem.connection.connect()
    socket_mock.assert_called_once_with('/var/run/tor/control')
    socket_mock.reset_mock()

    stem.connection.connect(control_port = None, control_socket = '/tmp/my_socket')
    socket_mock.assert_called_once_with('/tmp/my_socket')

  def _assert_connect_fails_with(self, args, stdout_mock, msg):
    result = stem.connection.connect(**args)

    if result is not None:
      self.fail()

    stdout_output = stdout_mock.getvalue()
    stdout_mock.truncate(0)
    self.assertEqual(msg, stdout_output.strip())

  @patch('stem.connection.authenticate')
  def test_auth_success(self, authenticate_mock):
    control_socket = Mock()

    stem.connection._connect_auth(control_socket, None, False, None, None)
    authenticate_mock.assert_called_with(control_socket, None, None)
    authenticate_mock.reset_mock()

    stem.connection._connect_auth(control_socket, 's3krit!!!', False, '/my/chroot', None)
    authenticate_mock.assert_called_with(control_socket, 's3krit!!!', '/my/chroot')

  @patch('getpass.getpass')
  @patch('stem.connection.authenticate')
  def test_auth_success_with_password_prompt(self, authenticate_mock, getpass_mock):
    control_socket = Mock()

    def authenticate_mock_func(controller, password, *args):
      if password is None:
        raise stem.connection.MissingPassword('no password')
      elif password == 'my_password':
        return None  # success
      else:
        raise ValueError('Unexpected authenticate_mock input: %s' % password)

    authenticate_mock.side_effect = authenticate_mock_func
    getpass_mock.return_value = 'my_password'

    stem.connection._connect_auth(control_socket, None, True, None, None)
    authenticate_mock.assert_any_call(control_socket, None, None)
    authenticate_mock.assert_any_call(control_socket, 'my_password', None)

  @patch('sys.stdout', new_callable = StringIO.StringIO)
  @patch('stem.connection.authenticate')
  def test_auth_failure(self, authenticate_mock, stdout_mock):
    control_socket = stem.socket.ControlPort(connect = False)

    authenticate_mock.side_effect = stem.connection.IncorrectSocketType('unable to connect to socket')
    self._assert_authenticate_fails_with(control_socket, stdout_mock, 'Please check in your torrc that 9051 is the ControlPort.')

    control_socket = stem.socket.ControlSocketFile(connect = False)

    self._assert_authenticate_fails_with(control_socket, stdout_mock, 'Are you sure the interface you specified belongs to')

    authenticate_mock.side_effect = stem.connection.UnrecognizedAuthMethods('unable to connect', ['telepathy'])
    self._assert_authenticate_fails_with(control_socket, stdout_mock, 'Tor is using a type of authentication we do not recognize...\n\n  telepathy')

    authenticate_mock.side_effect = stem.connection.IncorrectPassword('password rejected')
    self._assert_authenticate_fails_with(control_socket, stdout_mock, 'Incorrect password')

    authenticate_mock.side_effect = stem.connection.UnreadableCookieFile('permission denied', '/tmp/my_cookie', False)
    self._assert_authenticate_fails_with(control_socket, stdout_mock, "We were unable to read tor's authentication cookie...\n\n  Path: /tmp/my_cookie\n  Issue: permission denied")

    authenticate_mock.side_effect = stem.connection.OpenAuthRejected('crazy failure')
    self._assert_authenticate_fails_with(control_socket, stdout_mock, 'Unable to authenticate: crazy failure')

  def _assert_authenticate_fails_with(self, control_socket, stdout_mock, msg):
    result = stem.connection._connect_auth(control_socket, None, False, None, None)

    if result is not None:
      self.fail()  # _connect_auth() was successful

    stdout_output = stdout_mock.getvalue()
    stdout_mock.truncate(0)

    if not msg in stdout_output:
      self.fail("Expected...\n\n%s\n\n... which couldn't be found in...\n\n%s" % (msg, stdout_output))