[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Unit tests for PROTOCOLINFO responses
commit 2b797d0ba9310a015bef5bc2605020ebe8ffafdd
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sun Nov 13 13:15:49 2011 -0800
Unit tests for PROTOCOLINFO responses
---
run_tests.py | 2 +
stem/connection.py | 10 +-
test/unit/connection/__init__.py | 6 +
test/unit/connection/protocolinfo_response.py | 144 +++++++++++++++++++++++++
4 files changed, 158 insertions(+), 4 deletions(-)
diff --git a/run_tests.py b/run_tests.py
index 0b86706..1107a59 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -15,6 +15,7 @@ import test.runner
import test.unit.types.control_message
import test.unit.types.control_line
import test.unit.types.version
+import test.unit.connection.protocolinfo_response
import test.integ.message
import test.integ.system
@@ -29,6 +30,7 @@ DIVIDER = "=" * 70
UNIT_TESTS = (("stem.types.ControlMessage", test.unit.types.control_message.TestControlMessage),
("stem.types.ControlLine", test.unit.types.control_line.TestControlLine),
("stem.types.Version", test.unit.types.version.TestVerion),
+ ("stem.connection.ProtocolInfoResponse", test.unit.connection.protocolinfo_response.TestProtocolInfoResponse),
)
INTEG_TESTS = (("stem.types.ControlMessage", test.integ.message.TestMessageFunctions),
diff --git a/stem/connection.py b/stem/connection.py
index d17efde..2b96899 100644
--- a/stem/connection.py
+++ b/stem/connection.py
@@ -53,7 +53,8 @@ class ProtocolInfoResponse(stem.types.ControlMessage):
def convert(control_message):
"""
- Parses a ControlMessage, converting it into a ProtocolInfoResponse.
+ Parses a ControlMessage, performing an in-place conversion of it into a
+ ProtocolInfoResponse.
Arguments:
control_message (stem.types.ControlMessage) -
@@ -61,7 +62,7 @@ class ProtocolInfoResponse(stem.types.ControlMessage):
Raises:
stem.types.ProtocolError the message isn't a proper PROTOCOLINFO response
- ValueError if argument is of the wrong type
+ TypeError if argument isn't a ControlMessage
"""
if isinstance(control_message, stem.types.ControlMessage):
@@ -69,7 +70,7 @@ class ProtocolInfoResponse(stem.types.ControlMessage):
control_message._parse_message()
return control_message
else:
- raise ValueError("Only able to convert stem.types.ControlMessage instances")
+ raise TypeError("Only able to convert stem.types.ControlMessage instances")
convert = staticmethod(convert)
@@ -152,7 +153,7 @@ class ProtocolInfoResponse(stem.types.ControlMessage):
# parse optional COOKIEFILE mapping (quoted and can have escapes)
if line.is_next_mapping("COOKIEFILE", True, True):
- self.cookie_file = line.pop_mapping(True, True)[0]
+ self.cookie_file = line.pop_mapping(True, True)[1]
# attempt to expand relative cookie paths
if stem.util.system.is_relative_path(self.cookie_file):
@@ -286,6 +287,7 @@ class ControlConnection:
while self.is_running():
try:
+ # TODO: this raises a SocketClosed when... well, the socket is closed
control_message = stem.types.read_message(self._control_socket_file)
if control_message.content()[-1][0] == "650":
diff --git a/test/unit/connection/__init__.py b/test/unit/connection/__init__.py
new file mode 100644
index 0000000..440773e
--- /dev/null
+++ b/test/unit/connection/__init__.py
@@ -0,0 +1,6 @@
+"""
+Unit tests for stem.connection.
+"""
+
+__all__ = ["protocolinfo_response"]
+
diff --git a/test/unit/connection/protocolinfo_response.py b/test/unit/connection/protocolinfo_response.py
new file mode 100644
index 0000000..0dcde95
--- /dev/null
+++ b/test/unit/connection/protocolinfo_response.py
@@ -0,0 +1,144 @@
+"""
+Unit tests for the stem.connection.ProtocolInfoResponse class.
+"""
+
+import unittest
+import StringIO
+import stem.connection
+import stem.types
+
+NO_AUTH = """250-PROTOCOLINFO 1
+250-AUTH METHODS=NULL
+250-VERSION Tor="0.2.1.30"
+250 OK
+""".replace("\n", "\r\n")
+
+PASSWORD_AUTH = """250-PROTOCOLINFO 1
+250-AUTH METHODS=HASHEDPASSWORD
+250-VERSION Tor="0.2.1.30"
+250 OK
+""".replace("\n", "\r\n")
+
+COOKIE_AUTH = r"""250-PROTOCOLINFO 1
+250-AUTH METHODS=COOKIE COOKIEFILE="/tmp/my data\\\"dir//control_auth_cookie"
+250-VERSION Tor="0.2.1.30"
+250 OK
+""".replace("\n", "\r\n")
+
+MULTIPLE_AUTH = """250-PROTOCOLINFO 1
+250-AUTH METHODS=COOKIE,HASHEDPASSWORD COOKIEFILE="/home/atagar/.tor/control_auth_cookie"
+250-VERSION Tor="0.2.1.30"
+250 OK
+""".replace("\n", "\r\n")
+
+UNKNOWN_AUTH = """250-PROTOCOLINFO 1
+250-AUTH METHODS=MAGIC,HASHEDPASSWORD,PIXIE_DUST
+250-VERSION Tor="0.2.1.30"
+250 OK
+""".replace("\n", "\r\n")
+
+MINIMUM_RESPONSE = """250-PROTOCOLINFO 5
+250 OK
+""".replace("\n", "\r\n")
+
+class TestProtocolInfoResponse(unittest.TestCase):
+ """
+ Tests the parsing of ControlMessages for PROTOCOLINFO responses.
+ """
+
+ def test_convert(self):
+ """
+ Exercises functionality of the convert method both when it works and
+ there's an error.
+ """
+
+ # working case
+ control_message = stem.types.read_message(StringIO.StringIO(NO_AUTH))
+ stem.connection.ProtocolInfoResponse.convert(control_message)
+
+ # now this should be a ProtocolInfoResponse (ControlMessage subclass)
+ self.assertTrue(isinstance(control_message, stem.types.ControlMessage))
+ self.assertTrue(isinstance(control_message, stem.connection.ProtocolInfoResponse))
+
+ # exercise some of the ControlMessage functionality
+ self.assertTrue(str(control_message).startswith("PROTOCOLINFO 1"))
+ self.assertEquals(NO_AUTH, control_message.raw_content())
+
+ # attempt to convert the wrong type
+ self.assertRaises(TypeError, stem.connection.ProtocolInfoResponse.convert, "hello world")
+
+ # attempt to convert a different message type
+ bw_event_control_message = stem.types.read_message(StringIO.StringIO("650 BW 32326 2856\r\n"))
+ self.assertRaises(stem.types.ProtocolError, stem.connection.ProtocolInfoResponse.convert, bw_event_control_message)
+
+ def test_no_auth(self):
+ """
+ Checks a response when there's no authentication.
+ """
+
+ control_message = stem.types.read_message(StringIO.StringIO(NO_AUTH))
+ stem.connection.ProtocolInfoResponse.convert(control_message)
+
+ self.assertEquals(1, control_message.protocol_version)
+ self.assertEquals(stem.types.Version("0.2.1.30"), control_message.tor_version)
+ self.assertEquals((stem.connection.AuthMethod.NONE, ), control_message.auth_methods)
+ self.assertEquals((), control_message.unknown_auth_methods)
+ self.assertEquals(None, control_message.cookie_file)
+ self.assertEquals(None, control_message.socket)
+
+ def test_password_auth(self):
+ """
+ Checks a response with password authentication.
+ """
+
+ control_message = stem.types.read_message(StringIO.StringIO(PASSWORD_AUTH))
+ stem.connection.ProtocolInfoResponse.convert(control_message)
+ self.assertEquals((stem.connection.AuthMethod.PASSWORD, ), control_message.auth_methods)
+
+ def test_cookie_auth(self):
+ """
+ Checks a response with cookie authentication and a path including escape
+ characters.
+ """
+
+ control_message = stem.types.read_message(StringIO.StringIO(COOKIE_AUTH))
+ stem.connection.ProtocolInfoResponse.convert(control_message)
+ self.assertEquals((stem.connection.AuthMethod.COOKIE, ), control_message.auth_methods)
+ self.assertEquals("/tmp/my data\\\"dir//control_auth_cookie", control_message.cookie_file)
+
+ def test_multiple_auth(self):
+ """
+ Checks a response with multiple authentication methods.
+ """
+
+ control_message = stem.types.read_message(StringIO.StringIO(MULTIPLE_AUTH))
+ stem.connection.ProtocolInfoResponse.convert(control_message)
+ self.assertEquals((stem.connection.AuthMethod.COOKIE, stem.connection.AuthMethod.PASSWORD), control_message.auth_methods)
+ self.assertEquals("/home/atagar/.tor/control_auth_cookie", control_message.cookie_file)
+
+ def test_unknown_auth(self):
+ """
+ Checks a response with an unrecognized authtentication method.
+ """
+
+ control_message = stem.types.read_message(StringIO.StringIO(UNKNOWN_AUTH))
+ stem.connection.ProtocolInfoResponse.convert(control_message)
+ self.assertEquals((stem.connection.AuthMethod.UNKNOWN, stem.connection.AuthMethod.PASSWORD), control_message.auth_methods)
+ self.assertEquals(("MAGIC", "PIXIE_DUST"), control_message.unknown_auth_methods)
+
+ def test_minimum_response(self):
+ """
+ Checks a PROTOCOLINFO response that only contains the minimum amount of
+ information to be a valid response.
+ """
+
+ control_message = stem.types.read_message(StringIO.StringIO(MINIMUM_RESPONSE))
+ stem.connection.ProtocolInfoResponse.convert(control_message)
+
+ self.assertEquals(5, control_message.protocol_version)
+ self.assertEquals(None , control_message.tor_version)
+ self.assertEquals((), control_message.auth_methods)
+ self.assertEquals((), control_message.unknown_auth_methods)
+ self.assertEquals(None, control_message.cookie_file)
+ self.assertEquals(None, control_message.socket)
+
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits