[tor-commits] [bridgedb/master] Refactor unittests for bridgedb.parse.networkstatus.parseRLine().

isis at torproject.org isis at torproject.org
Sun Jan 12 06:06:33 UTC 2014


commit 56f7a51adbe2278bc7894390f5c1f5bf29b517c2
Author: Isis Lovecruft <isis at torproject.org>
Date:   Sat Dec 7 12:54:10 2013 +0000

    Refactor unittests for bridgedb.parse.networkstatus.parseRLine().
---
 lib/bridgedb/test/test_parse_networkstatus.py |  210 +++++++++++++++++++++----
 1 file changed, 180 insertions(+), 30 deletions(-)

diff --git a/lib/bridgedb/test/test_parse_networkstatus.py b/lib/bridgedb/test/test_parse_networkstatus.py
index 830f96c..5467a85 100644
--- a/lib/bridgedb/test/test_parse_networkstatus.py
+++ b/lib/bridgedb/test/test_parse_networkstatus.py
@@ -16,7 +16,11 @@ module is functioning correctly.
 """
 
 from __future__ import print_function
+from __future__ import unicode_literals
 
+import binascii
+
+from twisted.python import log
 from twisted.trial import unittest
 from bridgedb.parse import networkstatus
 
@@ -24,6 +28,14 @@ import sure
 from sure import this, these, those, the, it
 
 
+logFormat  = "%(created)d [%(levelname)s] %(module)s.%(funcName)s(): "
+logFormat += "%(message)s"
+networkstatus.logging.basicConfig(
+    filename='test_parse_networkstatus.log',
+    level=networkstatus.logging.DEBUG,
+    flags='w', format=logFormat)
+
+
 class ParseNetworkStatusRLineTests(unittest.TestCase):
     """Tests for :func:`bridgedb.parse.networkstatus.parseRLine`."""
 
@@ -36,25 +48,62 @@ class ParseNetworkStatusRLineTests(unittest.TestCase):
     port  = '9001'
     dirp  = '0'
 
+    def makeRLine(self, *args, **kwargs):
+        """Concatenate parameters into an 'r'-line and store the result as
+        ``self.line``.
+
+        To create an invalid networkstatus 'r'-line, for example with an
+        invalid IP address, use me like this:
+
+        >>> makeRLine(ip='0.0.0.0')
+
+        :keywords: The keyword arguments may be any of the class variables,
+            i.e. 'nick' or 'ident', and the variables should be similar to the
+            defaults in the class variables. If not given as parameters, the
+            class variables will be used.
+        """
+        line = []
+        for kw in ('pre', 'nick', 'ident', 'desc', 'ts', 'ip', 'port', 'dirp'):
+            if kw in kwargs.keys():
+                if kwargs[kw]:
+                    line.append(kwargs[kw])
+                elif kwargs[kw] is False:
+                    pass
+            else:
+                line.append(getattr(self, kw, ''))
+
+        self.line = ' '.join([l for l in line]).strip()
+        log.msg("\n  Testing networkstatusline:\n    %r..." % self.line)
+        self.assertTrue(self.line != '')
+
+    def tearDown(self):
+        self.line = ''
+
+    def assertAllFieldsAreNone(self, fields):
+        """Assert that every field in the iterable ``fields`` is None."""
+        for field in fields:
+            self.assertTrue(field is None)
+
     def test_missingPrefix(self):
-        line = ' '.join([self.nick, self.ident, self.desc,
-                         self.ts, self.ip, self.port, self.dirp])
-        self.assertRaises(networkstatus.NetworkstatusParsingError,
-                          networkstatus.parseRLine, line)
+        """Test a networkstatus 'r'-line that is missing the 'r ' prefix."""
+        self.makeRLine(pre=False)
+        fields = networkstatus.parseRLine(self.line)
+        self.assertAllFieldsAreNone(fields)
 
     def test_wrongNumberOfFields(self):
-        line = ' '.join([self.pre, self.nick, self.ident, self.ts, self.ip])
-        self.assertRaises(networkstatus.NetworkstatusParsingError,
-                          networkstatus.parseRLine, line)
+        """Test a line missing digest, ORPort, and DirPort fields."""
+        self.makeRLine(desc=False, port=False, dirp=False)
+        fields = networkstatus.parseRLine(self.line)
+        self.assertAllFieldsAreNone(fields)
 
     def test_wrongFieldOrder(self):
-        line = ' '.join([self.pre, self.nick, self.desc, self.ident,
-                         self.ts, self.ip, self.port, self.dirp])
-        fields = networkstatus.parseRLine(line)
+        """Test a line with the identity and descriptor digests switched."""
+        self.makeRLine(desc=self.ident, ident=self.desc)
+        fields = networkstatus.parseRLine(self.line)
         nick, others = fields[0], fields[1:]
 
         this(nick).should.be.ok
-        this(nick).should.be.a(str)
+        this(nick).should.be.a(basestring)
         this(nick).should.equal(self.nick)
 
         the(others).should.be.a(tuple)
@@ -62,31 +111,132 @@ class ParseNetworkStatusRLineTests(unittest.TestCase):
         for other in others:
             the(other).should.be(None)
 
-    def test_invalidTimestampMissingDate(self):
-        line = ' '.join([self.pre, self.nick, self.ident, self.desc,
-                         '15:15:15', self.ip, self.port, self.dirp])
-        self.assertRaises(networkstatus.NetworkstatusParsingError,
-                          networkstatus.parseRLine, line)
+    def test_invalidNicknameNonAlphanumeric(self):
+        """Test a line with a non-alphanumeric router nickname."""
+        self.makeRLine(nick='abcdef/*comment*/')
+        fields = networkstatus.parseRLine(self.line)
+        nick, ident, desc = fields[:3]
+        this(nick).should.be(None)
+        the(ident).should.be.a(basestring)
+        the(desc).should.be(None)
+
+    def test_invalidNicknameTooLong(self):
+        """Test a line with a router nickname which is way too long."""
+        self.makeRLine(nick='ThisIsAReallyReallyLongRouterNickname')
+        fields = networkstatus.parseRLine(self.line)
+        nick, ident, desc = fields[:3]
+        this(nick).should.be(None)
+        the(ident).should.be.a(basestring)
+        the(desc).should.be(None)
 
-    def test_invalidBase64(self):
-        line = ' '.join([self.pre, self.nick, '%$>#@,<', self.desc,
-                         self.ts, self.ip, self.port, self.dirp])
-        nick, ident, desc, ts, ip, port, dirp = networkstatus.parseRLine(line)
+    def test_invalidIdentBase64(self):
+        """Test line with '%$>@,<' for an identity digest."""
+        self.makeRLine(ident='%$>#@,<')
+        (nick, ident, desc, ts,
+         ip, port, dirp) = networkstatus.parseRLine(self.line)
 
         the(nick).should.be.ok
-        the(nick).should.be.a(str)
+        the(nick).should.be.a(basestring)
         the(nick).should.equal(self.nick)
-
         the(ident).should.be(None)
         the(desc).should.be(None)
 
+    def test_invalidIdentSingleQuoteChar(self):
+        """Test a line with a single quote character for the identity digest."""
+        self.makeRLine(ident=chr(0x27))
+        fields = networkstatus.parseRLine(self.line)
+        nick, ident, desc = fields[:3]
+
+        the(nick).should.be.ok
+        the(nick).should.be.a(basestring)
+        the(nick).should.be.equal(str(self.nick))
+        the(ident).should.be.equal(None)
+        the(desc).should.be.equal(None)
+
+    def test_invalidDescriptorDigest(self):
+        """Test an 'r'-line with invalid base64 descriptor digest."""
+        self.makeRLine(desc='敃噸襶')
+        fields = networkstatus.parseRLine(self.line)
+        nick, ident, desc, ts, ip = fields[:5]
+
+        the(nick).should.be.ok
+        the(nick).should.be.a(basestring)
+        the(nick).should.be.equal(str(self.nick))
+
+        b64ident = binascii.b2a_base64(ident).strip().rstrip('==')
+        the(ident).should.be.a(basestring)
+        this(b64ident).should.be.a(basestring)
+        this(b64ident).should.be.equal(self.ident)
+
+        the(desc).should.be.equal(None)
+        the(ts).should.be.equal(None)
+        the(ip).should.be.equal(None)
+
+    def test_invalidDescriptorDigest_missingBase64padding(self):
+        """Test a line with invalid base64 (no padding) descriptor digest."""
+        self.makeRLine(desc=self.desc.rstrip('=='))
+        fields = networkstatus.parseRLine(self.line)
+        nick, ident, desc, ts, ip = fields[:5]
+
+        the(nick).should.be.ok
+        the(nick).should.be.a(basestring)
+        the(nick).should.be.equal(str(self.nick))
+
+        b64ident = binascii.b2a_base64(ident).strip().rstrip('==')
+        the(ident).should.be.a(basestring)
+        this(b64ident).should.be.a(basestring)
+        this(b64ident).should.be.equal(self.ident)
+
+        the(desc).should.be.equal(None)
+        the(ts).should.be.equal(None)
+        the(ip).should.be.equal(None)
+
+    def test_missingAfterDesc(self):
+        """Test a line that has a valid descriptor digest, and is missing
+        everything after the descriptor digest, i.e. the timestamp, IP address,
+        and DirPort.
+        """
+        self.makeRLine(nick='missingAfterDesc', ts=False, ip=False, dirp=False)
+        fields = networkstatus.parseRLine(self.line)
+        self.assertAllFieldsAreNone(fields)
+
+    def test_missingAfterIdent(self):
+        """Test a line that and is missing the descriptor digest and
+        everything after it, i.e. the timestamp, IP address, and DirPort.
+        """
+        self.makeRLine(nick='noDesc', desc=False, ts=False,
+                       ip=False, dirp=False)
+        fields = networkstatus.parseRLine(self.line)
+        self.assertAllFieldsAreNone(fields)
+
     def test_invalidTimestamp(self):
-        line = ' '.join([self.pre, self.nick, self.ident, self.desc,
-                         '123456789 987654321', self.ip, self.port, self.dirp])
-        fields = networkstatus.parseRLine(line)
-        
+        """Test line with two large integers for the timestamp."""
+        self.makeRLine(ts='123456789 987654321')
+        fields = networkstatus.parseRLine(self.line)
+
+    def test_invalidTimestampMissingDate(self):
+        """Test a line where the timestamp is missing the date portion."""
+        self.makeRLine(ts='15:15:15')
+        fields = networkstatus.parseRLine(self.line)
+        self.assertAllFieldsAreNone(fields)
+
     def test_invalidIPAddress(self):
-        line = ' '.join([self.pre, self.nick, self.ident, self.desc,
-                         self.ts, '0.0.0.0', self.port, self.dirp])
-        fields = networkstatus.parseRLine(line)
-        
+        """Test a line with an invalid IP address."""
+        self.makeRLine(ip='0.0.0.0')
+        fields = networkstatus.parseRLine(self.line)
+        nick, ident, desc, ts, ip, port = fields[:6]
+
+        the(nick).should.be.equal(self.nick)
+
+        b64ident = binascii.b2a_base64(ident).strip().strip('==')
+        the(ident).should.be.a(basestring)
+        this(b64ident).should.be.a(basestring)
+        this(b64ident).should.be.equal(self.ident)
+
+        b64desc = binascii.b2a_base64(desc).strip()
+        the(desc).should.be.a(basestring)
+        this(b64desc).should.be.a(basestring)
+        this(b64desc).should.be.equal(self.desc)
+
+        the(ts).should.be.a(float)
+        the(ip).should.be(None)





More information about the tor-commits mailing list