commit 144692cb801bd421b107db142e6e1e034961518e Author: Damian Johnson atagar@torproject.org Date: Sun May 21 18:16:47 2017 -0700
Add normalize argument to ControlMessage.from_str()
Our get_message() testing helper just did a little normalization. Adding this to ControlMessage.from_str() so callers don't need to do the whole carriage return stuff. --- stem/response/__init__.py | 13 ++++++++++++- test/unit/doctest.py | 6 +++--- test/unit/interpreter/commands.py | 17 +++++----------- test/unit/response/add_onion.py | 21 +++++++------------- test/unit/response/authchallenge.py | 7 +++---- test/unit/response/events.py | 7 ++----- test/unit/response/getconf.py | 25 ++++++++---------------- test/unit/response/getinfo.py | 27 +++++++++---------------- test/unit/response/mapaddress.py | 23 ++++++++-------------- test/unit/response/protocolinfo.py | 39 ++++++++++++------------------------- test/unit/response/singleline.py | 23 +++++++--------------- test/unit/tutorial_examples.py | 9 +++------ test/util.py | 27 +------------------------ 13 files changed, 80 insertions(+), 164 deletions(-)
diff --git a/stem/response/__init__.py b/stem/response/__init__.py index a84654c..eadb25c 100644 --- a/stem/response/__init__.py +++ b/stem/response/__init__.py @@ -132,19 +132,30 @@ class ControlMessage(object): """
@staticmethod - def from_str(content, msg_type = None, **kwargs): + def from_str(content, msg_type = None, normalize = False, **kwargs): """ Provides a ControlMessage for the given content.
.. versionadded:: 1.1.0
+ .. versionchanged:: 1.6.0 + Added the normalize argument. + :param str content: message to construct the message from :param str msg_type: type of tor reply to parse the content as + :param bool normalize: ensures expected carriage return and ending newline + are present :param kwargs: optional keyword arguments to be passed to the parser method
:returns: stem.response.ControlMessage instance """
+ if normalize: + if not content.endswith('\n'): + content += '\n' + + content = re.sub('([\r]?)\n', '\r\n', content) + msg = stem.socket.recv_message(io.StringIO(stem.util.str_tools._to_unicode(content)))
if msg_type is not None: diff --git a/test/unit/doctest.py b/test/unit/doctest.py index 06a6eaa..1240324 100644 --- a/test/unit/doctest.py +++ b/test/unit/doctest.py @@ -13,9 +13,10 @@ import stem.util.connection import stem.util.str_tools import stem.util.system import stem.version - import test.util
+from stem.response import ControlMessage + try: # added in python 3.3 from unittest.mock import Mock, patch @@ -83,8 +84,7 @@ class TestDocumentation(unittest.TestCase): 'circuit-status': EXPECTED_CIRCUIT_STATUS, }[arg]
- response = test.util.get_message(ADD_ONION_RESPONSE) - stem.response.convert('ADD_ONION', response) + response = ControlMessage.from_str(ADD_ONION_RESPONSE, 'ADD_ONION', normalize = True) controller.create_ephemeral_hidden_service.return_value = response
args['globs'] = {'controller': controller} diff --git a/test/unit/interpreter/commands.py b/test/unit/interpreter/commands.py index c8cbc09..020b14b 100644 --- a/test/unit/interpreter/commands.py +++ b/test/unit/interpreter/commands.py @@ -5,10 +5,8 @@ import stem import stem.response import stem.version
-import test.util - from stem.interpreter.commands import ControlInterpreter, _get_fingerprint - +from stem.response import ControlMessage from test.unit.interpreter import CONTROLLER
try: @@ -126,8 +124,7 @@ class TestInterpreterCommands(unittest.TestCase): )
for content in event_contents: - event = test.util.get_message(content) - stem.response.convert('EVENT', event) + event = ControlMessage.from_str(content, 'EVENT', normalize = True) interpreter._received_events.append(event)
self.assertEqual(EXPECTED_EVENTS_RESPONSE, interpreter.run_command('/events')) @@ -168,10 +165,8 @@ class TestInterpreterCommands(unittest.TestCase): self.assertEqual(expected, interpreter.run_command('/unrecognized'))
def test_getinfo(self): - response = '250-version=0.2.5.1-alpha-dev (git-245ecfff36c0cecc)\r\n250 OK' - controller = Mock() - controller.msg.return_value = test.util.get_message(response) + controller.msg.return_value = ControlMessage.from_str('250-version=0.2.5.1-alpha-dev (git-245ecfff36c0cecc)\r\n250 OK\r\n')
interpreter = ControlInterpreter(controller)
@@ -183,10 +178,8 @@ class TestInterpreterCommands(unittest.TestCase): self.assertEqual('\x1b[1;31mkaboom!\x1b[0m\n', interpreter.run_command('getinfo process/user'))
def test_getconf(self): - response = '250-Log=notice stdout\r\n250 Address' - controller = Mock() - controller.msg.return_value = test.util.get_message(response) + controller.msg.return_value = ControlMessage.from_str('250-Log=notice stdout\r\n250 Address\r\n')
interpreter = ControlInterpreter(controller)
@@ -195,7 +188,7 @@ class TestInterpreterCommands(unittest.TestCase):
def test_setevents(self): controller = Mock() - controller.msg.return_value = test.util.get_message('250 OK') + controller.msg.return_value = ControlMessage.from_str('250 OK\r\n')
interpreter = ControlInterpreter(controller)
diff --git a/test/unit/response/add_onion.py b/test/unit/response/add_onion.py index 048ca67..9430250 100644 --- a/test/unit/response/add_onion.py +++ b/test/unit/response/add_onion.py @@ -8,7 +8,7 @@ import stem import stem.response import stem.response.add_onion
-import test.util +from stem.response import ControlMessage
WITH_PRIVATE_KEY = """250-ServiceID=gfzprpioee3hoppz 250-PrivateKey=RSA1024:MIICXgIBAAKBgQDZvYVxvKPTWhId/8Ss9fVxjAoFDsrJ3pk6HjHrEFRm3ypkK/vArbG9BrupzzYcyms+lO06O8b/iOSHuZI5mUEGkrYqQ+hpB2SkPUEzW7vcp8SQQivna3+LfkWH4JDqfiwZutU6MMEvU6g1OqK4Hll6uHbLpsfxkS/mGjyu1C9a9wIDAQABAoGBAJxsC3a25xZJqaRFfxwmIiptSTFy+/nj4T4gPQo6k/fHMKP/+P7liT9bm+uUwbITNNIjmPzxvrcKt+pNRR/92fizxr8QXr8l0ciVOLerbvdqvVUaQ/K1IVsblOLbactMvXcHactmqqLFUaZU9PPSDla7YkzikLDIUtHXQBEt4HEhAkEA/c4n+kpwi4odCaF49ESPbZC/Qejh7U9Tq10vAHzfrrGgQjnLw2UGDxJQXc9P12fGTvD2q3Q3VaMI8TKKFqZXsQJBANufh1zfP+xX/UfxJ4QzDUCHCu2gnyTDj3nG9Bc80E5g7NwR2VBXF1R+QQCK9GZcXd2y6vBYgrHOSUiLbVjGrycCQQDpOcs0zbjUEUuTsQUT+fiO50dJSrZpus6ZFxz85sMppeItWSzsVeYWbW7adYnZ2Gu72OPjM/0xPYsXEakhHSRRAkAxlVauNQjthv/72god4pi/VL224GiNmEkwKSa6iFRPHbrcBHuXk9IElWx/ft+mrHvUraw1DwaStgv9gNzzCghJAkEA08RegCRnIzuGvgeejLk4suIeCMD/11AvmSvxbRWS5rq1leSVo7uGLSnqDbwlzE4dGb5kH15NNAp14/l2Fu/yZg== @@ -40,8 +40,7 @@ class TestAddOnionResponse(unittest.TestCase): """
# working case - response = test.util.get_message(WITH_PRIVATE_KEY) - stem.response.convert('ADD_ONION', response) + response = ControlMessage.from_str(WITH_PRIVATE_KEY, 'ADD_ONION', normalize = True)
# now this should be a AddOnionResponse (ControlMessage subclass) self.assertTrue(isinstance(response, stem.response.ControlMessage)) @@ -57,9 +56,7 @@ class TestAddOnionResponse(unittest.TestCase): Checks a response when there's a private key. """
- response = test.util.get_message(WITH_PRIVATE_KEY) - stem.response.convert('ADD_ONION', response) - + response = ControlMessage.from_str(WITH_PRIVATE_KEY, 'ADD_ONION', normalize = True) self.assertEqual('gfzprpioee3hoppz', response.service_id) self.assertTrue(response.private_key.startswith('MIICXgIBAAKB')) self.assertEqual('RSA1024', response.private_key_type) @@ -70,9 +67,7 @@ class TestAddOnionResponse(unittest.TestCase): Checks a response when there's client credentials. """
- response = test.util.get_message(WITH_CLIENT_AUTH) - stem.response.convert('ADD_ONION', response) - + response = ControlMessage.from_str(WITH_CLIENT_AUTH, 'ADD_ONION', normalize = True) self.assertEqual('oekn5sqrvcu4wote', response.service_id) self.assertEqual(None, response.private_key) self.assertEqual(None, response.private_key_type) @@ -83,9 +78,7 @@ class TestAddOnionResponse(unittest.TestCase): Checks a response without a private key. """
- response = test.util.get_message(WITHOUT_PRIVATE_KEY) - stem.response.convert('ADD_ONION', response) - + response = ControlMessage.from_str(WITHOUT_PRIVATE_KEY, 'ADD_ONION', normalize = True) self.assertEqual('gfzprpioee3hoppz', response.service_id) self.assertEqual(None, response.private_key) self.assertEqual(None, response.private_key_type) @@ -95,7 +88,7 @@ class TestAddOnionResponse(unittest.TestCase): Checks a response that lack an initial service id. """
- response = test.util.get_message(WRONG_FIRST_KEY) + response = ControlMessage.from_str(WRONG_FIRST_KEY, normalize = True) self.assertRaisesRegexp(stem.ProtocolError, 'ADD_ONION response should start with', stem.response.convert, 'ADD_ONION', response)
def test_no_key_type(self): @@ -103,5 +96,5 @@ class TestAddOnionResponse(unittest.TestCase): Checks a response that's missing the private key type. """
- response = test.util.get_message(MISSING_KEY_TYPE) + response = ControlMessage.from_str(MISSING_KEY_TYPE, normalize = True) self.assertRaisesRegexp(stem.ProtocolError, 'ADD_ONION PrivateKey lines should be of the form', stem.response.convert, 'ADD_ONION', response) diff --git a/test/unit/response/authchallenge.py b/test/unit/response/authchallenge.py index 6a6533c..da195e1 100644 --- a/test/unit/response/authchallenge.py +++ b/test/unit/response/authchallenge.py @@ -8,7 +8,7 @@ import stem.response import stem.response.authchallenge import stem.socket
-import test.util +from stem.response import ControlMessage
VALID_RESPONSE = '250 AUTHCHALLENGE \ SERVERHASH=B16F72DACD4B5ED1531F3FCC04B593D46A1E30267E636EA7C7F8DD7A2B7BAA05 \ @@ -27,8 +27,7 @@ class TestAuthChallengeResponse(unittest.TestCase): Parses valid AUTHCHALLENGE responses. """
- control_message = test.util.get_message(VALID_RESPONSE) - stem.response.convert('AUTHCHALLENGE', control_message) + control_message = ControlMessage.from_str(VALID_RESPONSE, 'AUTHCHALLENGE', normalize = True)
# now this should be a AuthChallengeResponse (ControlMessage subclass) self.assertTrue(isinstance(control_message, stem.response.ControlMessage)) @@ -51,5 +50,5 @@ class TestAuthChallengeResponse(unittest.TestCase): # constructed.
remaining_comp = auth_challenge_comp[:index] + auth_challenge_comp[index + 1:] - control_message = test.util.get_message(' '.join(remaining_comp)) + control_message = ControlMessage.from_str(' '.join(remaining_comp), normalize = True) self.assertRaises(stem.ProtocolError, stem.response.convert, 'AUTHCHALLENGE', control_message) diff --git a/test/unit/response/events.py b/test/unit/response/events.py index b14b739..9031463 100644 --- a/test/unit/response/events.py +++ b/test/unit/response/events.py @@ -10,9 +10,8 @@ import stem.response import stem.response.events import stem.util.log
-import test.util - from stem import * # enums and exceptions +from stem.response import ControlMessage from stem.descriptor.router_status_entry import RouterStatusEntryV3
try: @@ -457,9 +456,7 @@ TB_EMPTY_BAD_2 = '650 TB_EMPTY GLOBAL READ=93 WRITTEN=93 LAST=-100'
def _get_event(content): - controller_event = test.util.get_message(content) - stem.response.convert('EVENT', controller_event) - return controller_event + return ControlMessage.from_str(content, 'EVENT', normalize = True)
class TestEvents(unittest.TestCase): diff --git a/test/unit/response/getconf.py b/test/unit/response/getconf.py index fb72ffc..c9765fc 100644 --- a/test/unit/response/getconf.py +++ b/test/unit/response/getconf.py @@ -8,9 +8,7 @@ import stem.response import stem.response.getconf import stem.socket
-import test.util - -EMPTY_RESPONSE = '250 OK' +from stem.response import ControlMessage
SINGLE_RESPONSE = """\ 250 DataDirectory=/home/neena/.tor""" @@ -42,8 +40,7 @@ class TestGetConfResponse(unittest.TestCase): Parses a GETCONF reply without options (just calling "GETCONF"). """
- control_message = test.util.get_message(EMPTY_RESPONSE) - stem.response.convert('GETCONF', control_message) + control_message = ControlMessage.from_str('250 OK\r\n', 'GETCONF')
# now this should be a GetConfResponse (ControlMessage subclass) self.assertTrue(isinstance(control_message, stem.response.ControlMessage)) @@ -56,8 +53,7 @@ class TestGetConfResponse(unittest.TestCase): Parses a GETCONF reply response for a single parameter. """
- control_message = test.util.get_message(SINGLE_RESPONSE) - stem.response.convert('GETCONF', control_message) + control_message = ControlMessage.from_str(SINGLE_RESPONSE, 'GETCONF', normalize = True) self.assertEqual({'DataDirectory': ['/home/neena/.tor']}, control_message.entries)
def test_batch_response(self): @@ -65,9 +61,6 @@ class TestGetConfResponse(unittest.TestCase): Parses a GETCONF reply for muiltiple parameters. """
- control_message = test.util.get_message(BATCH_RESPONSE) - stem.response.convert('GETCONF', control_message) - expected = { 'CookieAuthentication': ['0'], 'ControlPort': ['9100'], @@ -75,6 +68,7 @@ class TestGetConfResponse(unittest.TestCase): 'DirPort': [], }
+ control_message = ControlMessage.from_str(BATCH_RESPONSE, 'GETCONF', normalize = True) self.assertEqual(expected, control_message.entries)
def test_multivalue_response(self): @@ -82,14 +76,12 @@ class TestGetConfResponse(unittest.TestCase): Parses a GETCONF reply containing a single key with multiple parameters. """
- control_message = test.util.get_message(MULTIVALUE_RESPONSE) - stem.response.convert('GETCONF', control_message) - expected = { 'ControlPort': ['9100'], 'ExitPolicy': ['accept 34.3.4.5', 'accept 3.4.53.3', 'accept 3.4.53.3', 'reject 23.245.54.3'] }
+ control_message = ControlMessage.from_str(MULTIVALUE_RESPONSE, 'GETCONF', normalize = True) self.assertEqual(expected, control_message.entries)
def test_unrecognized_key_response(self): @@ -97,11 +89,10 @@ class TestGetConfResponse(unittest.TestCase): Parses a GETCONF reply that contains an error code with an unrecognized key. """
- control_message = test.util.get_message(UNRECOGNIZED_KEY_RESPONSE) - self.assertRaises(stem.InvalidArguments, stem.response.convert, 'GETCONF', control_message) - try: + control_message = ControlMessage.from_str(UNRECOGNIZED_KEY_RESPONSE, normalize = True) stem.response.convert('GETCONF', control_message) + self.fail('expected a stem.InvalidArguments to be raised') except stem.InvalidArguments as exc: self.assertEqual(exc.arguments, ['brickroad', 'submarine'])
@@ -112,5 +103,5 @@ class TestGetConfResponse(unittest.TestCase): GETCONF's spec. """
- control_message = test.util.get_message(INVALID_RESPONSE) + control_message = ControlMessage.from_str(INVALID_RESPONSE, normalize = True) self.assertRaises(stem.ProtocolError, stem.response.convert, 'GETCONF', control_message) diff --git a/test/unit/response/getinfo.py b/test/unit/response/getinfo.py index 2054a03..b08e311 100644 --- a/test/unit/response/getinfo.py +++ b/test/unit/response/getinfo.py @@ -9,9 +9,7 @@ import stem.response.getinfo import stem.socket import stem.util.str_tools
-import test.util - -EMPTY_RESPONSE = '250 OK' +from stem.response import ControlMessage
SINGLE_RESPONSE = """\ 250-version=0.2.3.11-alpha-dev @@ -57,8 +55,7 @@ class TestGetInfoResponse(unittest.TestCase): Parses a GETINFO reply without options (just calling "GETINFO"). """
- control_message = test.util.get_message(EMPTY_RESPONSE) - stem.response.convert('GETINFO', control_message) + control_message = ControlMessage.from_str('250 OK\r\n', 'GETINFO')
# now this should be a GetInfoResponse (ControlMessage subclass) self.assertTrue(isinstance(control_message, stem.response.ControlMessage)) @@ -71,8 +68,7 @@ class TestGetInfoResponse(unittest.TestCase): Parses a GETINFO reply response for a single parameter. """
- control_message = test.util.get_message(SINGLE_RESPONSE) - stem.response.convert('GETINFO', control_message) + control_message = ControlMessage.from_str(SINGLE_RESPONSE, 'GETINFO', normalize = True) self.assertEqual({'version': b'0.2.3.11-alpha-dev'}, control_message.entries)
def test_batch_response(self): @@ -80,15 +76,13 @@ class TestGetInfoResponse(unittest.TestCase): Parses a GETINFO reply for muiltiple parameters. """
- control_message = test.util.get_message(BATCH_RESPONSE) - stem.response.convert('GETINFO', control_message) - expected = { 'version': b'0.2.3.11-alpha-dev', 'address': b'67.137.76.214', 'fingerprint': b'5FDE0422045DF0E1879A3738D09099EB4A0C5BA0', }
+ control_message = ControlMessage.from_str(BATCH_RESPONSE, 'GETINFO', normalize = True) self.assertEqual(expected, control_message.entries)
def test_multiline_response(self): @@ -97,14 +91,12 @@ class TestGetInfoResponse(unittest.TestCase): value. """
- control_message = test.util.get_message(MULTILINE_RESPONSE) - stem.response.convert('GETINFO', control_message) - expected = { 'version': b'0.2.3.11-alpha-dev (git-ef0bc7f8f26a917c)', 'config-text': b'\n'.join(stem.util.str_tools._to_bytes(MULTILINE_RESPONSE).splitlines()[2:8]), }
+ control_message = ControlMessage.from_str(MULTILINE_RESPONSE, 'GETINFO', normalize = True) self.assertEqual(expected, control_message.entries)
def test_invalid_non_mapping_content(self): @@ -113,7 +105,7 @@ class TestGetInfoResponse(unittest.TestCase): entry. """
- control_message = test.util.get_message(NON_KEY_VALUE_ENTRY) + control_message = ControlMessage.from_str(NON_KEY_VALUE_ENTRY, normalize = True) self.assertRaises(stem.ProtocolError, stem.response.convert, 'GETINFO', control_message)
def test_unrecognized_key_response(self): @@ -121,11 +113,10 @@ class TestGetInfoResponse(unittest.TestCase): Parses a GETCONF reply that contains an error code with an unrecognized key. """
- control_message = test.util.get_message(UNRECOGNIZED_KEY_ENTRY) - self.assertRaises(stem.InvalidArguments, stem.response.convert, 'GETINFO', control_message) - try: + control_message = ControlMessage.from_str(UNRECOGNIZED_KEY_ENTRY, normalize = True) stem.response.convert('GETINFO', control_message) + self.fail('expected a stem.InvalidArguments to be raised') except stem.InvalidArguments as exc: self.assertEqual(exc.arguments, ['blackhole'])
@@ -136,5 +127,5 @@ class TestGetInfoResponse(unittest.TestCase): malformed according to the GETINFO's spec. """
- control_message = test.util.get_message(MISSING_MULTILINE_NEWLINE) + control_message = ControlMessage.from_str(MISSING_MULTILINE_NEWLINE, normalize = True) self.assertRaises(stem.ProtocolError, stem.response.convert, 'GETINFO', control_message) diff --git a/test/unit/response/mapaddress.py b/test/unit/response/mapaddress.py index 63813d4..7482507 100644 --- a/test/unit/response/mapaddress.py +++ b/test/unit/response/mapaddress.py @@ -8,9 +8,7 @@ import stem.response import stem.response.mapaddress import stem.socket
-import test.util - -SINGLE_RESPONSE = """250 foo=bar""" +from stem.response import ControlMessage
BATCH_RESPONSE = """\ 250-foo=bar @@ -36,8 +34,7 @@ class TestMapAddressResponse(unittest.TestCase): Parses a MAPADDRESS reply response with a single address mapping. """
- control_message = test.util.get_message(SINGLE_RESPONSE) - stem.response.convert('MAPADDRESS', control_message) + control_message = ControlMessage.from_str('250 foo=bar\r\n', 'MAPADDRESS') self.assertEqual({'foo': 'bar'}, control_message.entries)
def test_batch_response(self): @@ -45,9 +42,6 @@ class TestMapAddressResponse(unittest.TestCase): Parses a MAPADDRESS reply with multiple address mappings """
- control_message = test.util.get_message(BATCH_RESPONSE) - stem.response.convert('MAPADDRESS', control_message) - expected = { 'foo': 'bar', 'baz': 'quux', @@ -55,6 +49,7 @@ class TestMapAddressResponse(unittest.TestCase): '120.23.23.2': 'torproject.org' }
+ control_message = ControlMessage.from_str(BATCH_RESPONSE, 'MAPADDRESS', normalize = True) self.assertEqual(expected, control_message.entries)
def test_invalid_requests(self): @@ -62,13 +57,11 @@ class TestMapAddressResponse(unittest.TestCase): Parses a MAPADDRESS replies that contain an error code due to hostname syntax errors. """
- control_message = test.util.get_message(UNRECOGNIZED_KEYS_RESPONSE) + control_message = ControlMessage.from_str(UNRECOGNIZED_KEYS_RESPONSE, normalize = True) self.assertRaises(stem.InvalidRequest, stem.response.convert, 'MAPADDRESS', control_message) - expected = {'23': '324'}
- control_message = test.util.get_message(PARTIAL_FAILURE_RESPONSE) - stem.response.convert('MAPADDRESS', control_message) - self.assertEqual(expected, control_message.entries) + control_message = ControlMessage.from_str(PARTIAL_FAILURE_RESPONSE, 'MAPADDRESS', normalize = True) + self.assertEqual({'23': '324'}, control_message.entries)
def test_invalid_response(self): """ @@ -77,8 +70,8 @@ class TestMapAddressResponse(unittest.TestCase): MAPADDRESS's spec. """
- control_message = test.util.get_message(INVALID_EMPTY_RESPONSE) + control_message = ControlMessage.from_str(INVALID_EMPTY_RESPONSE, normalize = True) self.assertRaises(stem.ProtocolError, stem.response.convert, 'MAPADDRESS', control_message)
- control_message = test.util.get_message(INVALID_RESPONSE) + control_message = ControlMessage.from_str(INVALID_RESPONSE, normalize = True) self.assertRaises(stem.ProtocolError, stem.response.convert, 'MAPADDRESS', control_message) diff --git a/test/unit/response/protocolinfo.py b/test/unit/response/protocolinfo.py index d8fb762..9b2c9b1 100644 --- a/test/unit/response/protocolinfo.py +++ b/test/unit/response/protocolinfo.py @@ -12,8 +12,7 @@ import stem.util.proc import stem.util.system import stem.version
-import test.util - +from stem.response import ControlMessage from stem.response.protocolinfo import AuthMethod
try: @@ -71,8 +70,7 @@ class TestProtocolInfoResponse(unittest.TestCase): """
# working case - control_message = test.util.get_message(NO_AUTH) - stem.response.convert('PROTOCOLINFO', control_message) + control_message = ControlMessage.from_str(NO_AUTH, 'PROTOCOLINFO', normalize = True)
# now this should be a ProtocolInfoResponse (ControlMessage subclass) self.assertTrue(isinstance(control_message, stem.response.ControlMessage)) @@ -87,17 +85,14 @@ class TestProtocolInfoResponse(unittest.TestCase): self.assertRaises(TypeError, stem.response.convert, 'PROTOCOLINFO', 'hello world')
# attempt to convert a different message type - bw_event_control_message = test.util.get_message('650 BW 32326 2856') - self.assertRaises(stem.ProtocolError, stem.response.convert, 'PROTOCOLINFO', bw_event_control_message) + self.assertRaises(stem.ProtocolError, ControlMessage.from_str, '650 BW 32326 2856\r\n', 'PROTOCOLINFO')
def test_no_auth(self): """ Checks a response when there's no authentication. """
- control_message = test.util.get_message(NO_AUTH) - stem.response.convert('PROTOCOLINFO', control_message) - + control_message = ControlMessage.from_str(NO_AUTH, 'PROTOCOLINFO', normalize = True) self.assertEqual(1, control_message.protocol_version) self.assertEqual(stem.version.Version('0.2.1.30'), control_message.tor_version) self.assertEqual((AuthMethod.NONE, ), control_message.auth_methods) @@ -109,8 +104,7 @@ class TestProtocolInfoResponse(unittest.TestCase): Checks a response with password authentication. """
- control_message = test.util.get_message(PASSWORD_AUTH) - stem.response.convert('PROTOCOLINFO', control_message) + control_message = ControlMessage.from_str(PASSWORD_AUTH, 'PROTOCOLINFO', normalize = True) self.assertEqual((AuthMethod.PASSWORD, ), control_message.auth_methods)
def test_cookie_auth(self): @@ -119,8 +113,7 @@ class TestProtocolInfoResponse(unittest.TestCase): characters. """
- control_message = test.util.get_message(COOKIE_AUTH) - stem.response.convert('PROTOCOLINFO', control_message) + control_message = ControlMessage.from_str(COOKIE_AUTH, 'PROTOCOLINFO', normalize = True) self.assertEqual((AuthMethod.COOKIE, ), control_message.auth_methods) self.assertEqual('/tmp/my data\"dir//control_auth_cookie', control_message.cookie_path)
@@ -129,8 +122,7 @@ class TestProtocolInfoResponse(unittest.TestCase): Checks a response with multiple authentication methods. """
- control_message = test.util.get_message(MULTIPLE_AUTH) - stem.response.convert('PROTOCOLINFO', control_message) + control_message = ControlMessage.from_str(MULTIPLE_AUTH, 'PROTOCOLINFO', normalize = True) self.assertEqual((AuthMethod.COOKIE, AuthMethod.PASSWORD), control_message.auth_methods) self.assertEqual('/home/atagar/.tor/control_auth_cookie', control_message.cookie_path)
@@ -139,8 +131,7 @@ class TestProtocolInfoResponse(unittest.TestCase): Checks a response with an unrecognized authtentication method. """
- control_message = test.util.get_message(UNKNOWN_AUTH) - stem.response.convert('PROTOCOLINFO', control_message) + control_message = ControlMessage.from_str(UNKNOWN_AUTH, 'PROTOCOLINFO', normalize = True) self.assertEqual((AuthMethod.UNKNOWN, AuthMethod.PASSWORD), control_message.auth_methods) self.assertEqual(('MAGIC', 'PIXIE_DUST'), control_message.unknown_auth_methods)
@@ -150,9 +141,7 @@ class TestProtocolInfoResponse(unittest.TestCase): information to be a valid response. """
- control_message = test.util.get_message(MINIMUM_RESPONSE) - stem.response.convert('PROTOCOLINFO', control_message) - + control_message = ControlMessage.from_str(MINIMUM_RESPONSE, 'PROTOCOLINFO', normalize = True) self.assertEqual(5, control_message.protocol_version) self.assertEqual(None, control_message.tor_version) self.assertEqual((), control_message.auth_methods) @@ -165,8 +154,7 @@ class TestProtocolInfoResponse(unittest.TestCase): Checks an authentication cookie with a unicode path. """
- control_message = test.util.get_message(UNICODE_COOKIE_PATH) - stem.response.convert('PROTOCOLINFO', control_message) + control_message = ControlMessage.from_str(UNICODE_COOKIE_PATH, 'PROTOCOLINFO', normalize = True) self.assertEqual(EXPECTED_UNICODE_PATH, control_message.cookie_path)
@patch('stem.util.proc.is_available', Mock(return_value = False)) @@ -191,9 +179,7 @@ class TestProtocolInfoResponse(unittest.TestCase): with patch('stem.util.system.call') as call_mock: call_mock.side_effect = call_function
- control_message = test.util.get_message(RELATIVE_COOKIE_PATH) - stem.response.convert('PROTOCOLINFO', control_message) - + control_message = ControlMessage.from_str(RELATIVE_COOKIE_PATH, 'PROTOCOLINFO', normalize = True) stem.connection._expand_cookie_path(control_message, stem.util.system.pid_by_name, 'tor')
self.assertEqual(os.path.join('/tmp/foo', 'tor-browser_en-US', 'Data', 'control_auth_cookie'), control_message.cookie_path) @@ -202,6 +188,5 @@ class TestProtocolInfoResponse(unittest.TestCase): # leaving the path unexpanded)
with patch('stem.util.system.call', Mock(return_value = None)): - control_message = test.util.get_message(RELATIVE_COOKIE_PATH) - stem.response.convert('PROTOCOLINFO', control_message) + control_message = ControlMessage.from_str(RELATIVE_COOKIE_PATH, 'PROTOCOLINFO', normalize = True) self.assertEqual('./tor-browser_en-US/Data/control_auth_cookie', control_message.cookie_path) diff --git a/test/unit/response/singleline.py b/test/unit/response/singleline.py index 1c05aa5..76b252d 100644 --- a/test/unit/response/singleline.py +++ b/test/unit/response/singleline.py @@ -4,33 +4,24 @@ Unit tests for the stem.response.SingleLineResponse class.
import unittest
-import stem.response -import stem.socket +import stem
-import test.util - -MULTILINE_RESPONSE = """250-MULTI -250 LINE""" +from stem.response import ControlMessage
class TestSingleLineResponse(unittest.TestCase): def test_single_line_response(self): - message = test.util.get_message('552 NOTOK') - stem.response.convert('SINGLELINE', message) + message = ControlMessage.from_str('552 NOTOK\r\n', 'SINGLELINE') self.assertEqual(False, message.is_ok())
- message = test.util.get_message('250 KK') - stem.response.convert('SINGLELINE', message) + message = ControlMessage.from_str('250 KK\r\n', 'SINGLELINE') self.assertEqual(True, message.is_ok())
- message = test.util.get_message('250 OK') - stem.response.convert('SINGLELINE', message) + message = ControlMessage.from_str('250 OK\r\n', 'SINGLELINE') self.assertEqual(True, message.is_ok(True))
- message = test.util.get_message('250 HMM') - stem.response.convert('SINGLELINE', message) + message = ControlMessage.from_str('250 HMM\r\n', 'SINGLELINE') self.assertEqual(False, message.is_ok(True))
def test_multi_line_response(self): - message = test.util.get_message(MULTILINE_RESPONSE) - self.assertRaises(stem.ProtocolError, stem.response.convert, 'SINGLELINE', message) + self.assertRaises(stem.ProtocolError, ControlMessage.from_str, '250-MULTI\r\n250 LINE\r\n', 'SINGLELINE') diff --git a/test/unit/tutorial_examples.py b/test/unit/tutorial_examples.py index 2075bdf..50e766d 100644 --- a/test/unit/tutorial_examples.py +++ b/test/unit/tutorial_examples.py @@ -15,14 +15,13 @@ import stem.response import stem.descriptor.remote import stem.prereq
-import test.util - from stem.control import Controller -from stem.util import str_type from stem.descriptor.networkstatus import NetworkStatusDocumentV3 from stem.descriptor.remote import DIRECTORY_AUTHORITIES from stem.descriptor.router_status_entry import ROUTER_STATUS_ENTRY_V3_HEADER, RouterStatusEntryV3 from stem.descriptor.server_descriptor import RelayDescriptor +from stem.response import ControlMessage +from stem.util import str_type
from test.unit import exec_documentation_example
@@ -100,9 +99,7 @@ A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB: caerSidi
def _get_event(content): - controller_event = test.util.get_message(content) - stem.response.convert('EVENT', controller_event) - return controller_event + return ControlMessage.from_str(content, 'EVENT', normalize = True)
def _get_circ_event(id, status, hop1, hop2, hop3, purpose): diff --git a/test/util.py b/test/util.py index 47d90fd..7ad309d 100644 --- a/test/util.py +++ b/test/util.py @@ -12,7 +12,6 @@ Helper functions for our test framework. get_prereq - provides the tor version required to run the given target get_torrc_entries - provides the torrc entries for a given target
- get_message - provides a ControlMessage instance get_protocolinfo_response - provides a ProtocolInfoResponse instance get_all_combinations - provides all combinations of attributes random_fingerprint - provides a random relay fingerprint @@ -21,7 +20,6 @@ Helper functions for our test framework.
import hashlib import itertools -import re import os
import stem @@ -250,29 +248,6 @@ def random_fingerprint(): return hashlib.sha1(os.urandom(20)).hexdigest().upper()
-def get_message(content, reformat = True): - """ - Provides a ControlMessage with content modified to be parsable. This makes - the following changes unless 'reformat' is false... - - * ensures the content ends with a newline - * newlines are replaced with a carriage return and newline pair - - :param str content: base content for the controller message - :param str reformat: modifies content to be more accommodating to being parsed - - :returns: stem.response.ControlMessage instance - """ - - if reformat: - if not content.endswith('\n'): - content += '\n' - - content = re.sub('([\r]?)\n', '\r\n', content) - - return stem.response.ControlMessage.from_str(content) - - def get_protocolinfo_response(**attributes): """ Provides a ProtocolInfoResponse, customized with the given attributes. The @@ -284,7 +259,7 @@ def get_protocolinfo_response(**attributes): :returns: stem.response.protocolinfo.ProtocolInfoResponse instance """
- protocolinfo_response = get_message('250-PROTOCOLINFO 1\n250 OK') + protocolinfo_response = stem.response.ControlMessage.from_str('250-PROTOCOLINFO 1\r\n250 OK\r\n', 'PROTOCOLINFO') stem.response.convert('PROTOCOLINFO', protocolinfo_response)
for attr in attributes: