commit 1d467aee328887fb4259ebc498a6b8ddebc8e81d Author: Damian Johnson atagar@torproject.org Date: Mon May 7 10:40:31 2018 -0700
Initial Authority.from_remote() unit tests
Adopting a couple Fallback tests for its Authority counterpart. The persistance tests aren't relevant to it (authorities are managed by hand). As for the from_str() tests I need to give this more thought. Maybe refactor the directory module a bit first. --- test/unit/directory/authority.py | 52 ++++++++++++++++++ test/unit/directory/fallback.py | 110 +++++++++++++++++++-------------------- 2 files changed, 107 insertions(+), 55 deletions(-)
diff --git a/test/unit/directory/authority.py b/test/unit/directory/authority.py index 4a5f3a12..dcee4916 100644 --- a/test/unit/directory/authority.py +++ b/test/unit/directory/authority.py @@ -2,9 +2,29 @@ Unit tests for stem.directory.Authority. """
+import io import unittest
import stem.directory +import stem.prereq + +try: + # added in python 3.3 + from unittest.mock import patch, Mock +except ImportError: + from mock import patch, Mock + +URL_OPEN = 'urllib.request.urlopen' if stem.prereq.is_python_3() else 'urllib2.urlopen' + +AUTHORITY_GITWEB_CONTENT = b"""\ +"moria1 orport=9101 " + "v3ident=D586D18309DED4CD6D57C18FDB97EFA96D330566 " + "128.31.0.39:9131 9695 DFC3 5FFE B861 329B 9F1A B04C 4639 7020 CE31", +"tor26 orport=443 " + "v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 " + "ipv6=[2001:858:2:2:aabb:0:563b:1526]:443 " + "86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D", +"""
class TestAuthority(unittest.TestCase): @@ -26,3 +46,35 @@ class TestAuthority(unittest.TestCase): second_authority = dict(authority_attr) second_authority[attr] = value self.assertNotEqual(stem.directory.Authority(**authority_attr), stem.directory.Authority(**second_authority)) + + def test_from_cache(self): + authorities = stem.directory.Authority.from_cache() + self.assertTrue(len(authorities) > 4) + self.assertEqual('128.31.0.39', authorities['moria1'].address) + + @patch(URL_OPEN, Mock(return_value = io.BytesIO(AUTHORITY_GITWEB_CONTENT))) + def test_from_remote(self): + expected = { + 'moria1': stem.directory.Authority( + nickname = 'moria1', + address = '128.31.0.39', + or_port = 9101, + dir_port = 9131, + fingerprint = '9695DFC35FFEB861329B9F1AB04C46397020CE31', + v3ident = 'D586D18309DED4CD6D57C18FDB97EFA96D330566', + ), + 'tor26': stem.directory.Authority( + nickname = 'tor26', + address = '86.59.21.38', + or_port = 443, + dir_port = 80, + fingerprint = '847B1F850344D7876491A54892F904934E4EB85D', + v3ident = '14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4', + ), + } + + self.assertEqual(expected, stem.directory.Authority.from_remote()) + + @patch(URL_OPEN, Mock(return_value = io.BytesIO(b''))) + def test_from_remote_empty(self): + self.assertRaisesRegexp(IOError, 'did not have any content', stem.directory.Authority.from_remote) diff --git a/test/unit/directory/fallback.py b/test/unit/directory/fallback.py index cd857b9f..1cbff9a3 100644 --- a/test/unit/directory/fallback.py +++ b/test/unit/directory/fallback.py @@ -23,7 +23,7 @@ except ImportError:
URL_OPEN = 'urllib.request.urlopen' if stem.prereq.is_python_3() else 'urllib2.urlopen'
-FALLBACK_DIR_CONTENT = b"""\ +FALLBACK_GITWEB_CONTENT = b"""\ /* type=fallback */ /* version=2.0.0 */ /* timestamp=20170526090242 */ @@ -63,6 +63,12 @@ FALLBACK_ENTRY = b"""\ /* extrainfo=1 */ """
+HEADER = OrderedDict(( + ('type', 'fallback'), + ('version', '2.0.0'), + ('timestamp', '20170526090242'), +)) +
class TestFallback(unittest.TestCase): def test_equality(self): @@ -90,16 +96,12 @@ class TestFallback(unittest.TestCase): self.assertNotEqual(stem.directory.Fallback(**fallback_attr), stem.directory.Fallback(**second_fallback))
def test_from_cache(self): - # quick sanity test that we can load cached content - fallback_directories = stem.directory.Fallback.from_cache() - self.assertTrue(len(fallback_directories) > 10) - self.assertEqual('5.39.92.199', fallback_directories['0BEA4A88D069753218EAAAD6D22EA87B9A1319D6'].address) + fallbacks = stem.directory.Fallback.from_cache() + self.assertTrue(len(fallbacks) > 10) + self.assertEqual('5.39.92.199', fallbacks['0BEA4A88D069753218EAAAD6D22EA87B9A1319D6'].address)
- @patch(URL_OPEN, Mock(return_value = io.BytesIO(FALLBACK_DIR_CONTENT))) + @patch(URL_OPEN, Mock(return_value = io.BytesIO(FALLBACK_GITWEB_CONTENT))) def test_from_remote(self): - fallback_directories = stem.directory.Fallback.from_remote() - header = OrderedDict((('type', 'fallback'), ('version', '2.0.0'), ('timestamp', '20170526090242'))) - expected = { '0756B7CD4DFC8182BE23143FAC0642F515182CEB': stem.directory.Fallback( address = '5.9.110.236', @@ -109,7 +111,7 @@ class TestFallback(unittest.TestCase): nickname = 'rueckgrat', has_extrainfo = True, orport_v6 = ('2a01:4f8:162:51e2::2', 9001), - header = header, + header = HEADER, ), '01A9258A46E97FF8B2CAC7910577862C14F2C524': stem.directory.Fallback( address = '193.171.202.146', @@ -119,15 +121,51 @@ class TestFallback(unittest.TestCase): nickname = None, has_extrainfo = False, orport_v6 = None, - header = header, + header = HEADER, ), }
- self.assertEqual(expected, fallback_directories) + self.assertEqual(expected, stem.directory.Fallback.from_remote())
- def test_persistence(self): - header = OrderedDict((('type', 'fallback'), ('version', '2.0.0'), ('timestamp', '20170526090242'))) + @patch(URL_OPEN, Mock(return_value = io.BytesIO(b''))) + def test_from_remote_empty(self): + self.assertRaisesRegexp(IOError, 'did not have any content', stem.directory.Fallback.from_remote) + + @patch(URL_OPEN, Mock(return_value = io.BytesIO(b'\n'.join(FALLBACK_GITWEB_CONTENT.splitlines()[1:])))) + def test_from_remote_no_header(self): + self.assertRaisesRegexp(IOError, 'does not have a type field indicating it is fallback directory metadata', stem.directory.Fallback.from_remote) + + @patch(URL_OPEN, Mock(return_value = io.BytesIO(FALLBACK_GITWEB_CONTENT.replace(b'version=2.0.0', b'version')))) + def test_from_remote_malformed_header(self): + self.assertRaisesRegexp(IOError, 'Malformed fallback directory header line: /* version */', stem.directory.Fallback.from_remote) + + def test_from_str(self): + expected = stem.directory.Fallback( + address = '5.9.110.236', + or_port = 9001, + dir_port = 9030, + fingerprint = '0756B7CD4DFC8182BE23143FAC0642F515182CEB', + nickname = 'rueckgrat', + has_extrainfo = True, + orport_v6 = ('2a01:4f8:162:51e2::2', 9001), + ) + + self.assertEqual(expected, stem.directory.Fallback._from_str(FALLBACK_ENTRY)) + + def test_from_str_malformed(self): + test_values = { + FALLBACK_ENTRY.replace(b'id=0756B7CD4DFC8182BE23143FAC0642F515182CEB', b''): 'Malformed fallback address line:', + FALLBACK_ENTRY.replace(b'5.9.110.236', b'5.9.110'): '0756B7CD4DFC8182BE23143FAC0642F515182CEB has an invalid IPv4 address: 5.9.110', + FALLBACK_ENTRY.replace(b':9030', b':7814713228'): '0756B7CD4DFC8182BE23143FAC0642F515182CEB has an invalid dir_port: 7814713228', + FALLBACK_ENTRY.replace(b'orport=9001', b'orport=7814713228'): '0756B7CD4DFC8182BE23143FAC0642F515182CEB has an invalid or_port: 7814713228', + FALLBACK_ENTRY.replace(b'ipv6=[2a01', b'ipv6=[:::'): '0756B7CD4DFC8182BE23143FAC0642F515182CEB has an invalid IPv6 address: ::::4f8:162:51e2::2', + FALLBACK_ENTRY.replace(b'nickname=rueckgrat', b'nickname=invalid~nickname'): '0756B7CD4DFC8182BE23143FAC0642F515182CEB has an invalid nickname: invalid~nickname', + } + + for entry, expected in test_values.items(): + self.assertRaisesRegexp(ValueError, expected, stem.directory.Fallback._from_str, entry)
+ def test_persistence(self): expected = { '0756B7CD4DFC8182BE23143FAC0642F515182CEB': stem.directory.Fallback( address = '5.9.110.236', @@ -137,7 +175,7 @@ class TestFallback(unittest.TestCase): nickname = 'rueckgrat', has_extrainfo = True, orport_v6 = ('2a01:4f8:162:51e2::2', 9001), - header = header, + header = HEADER, ), '01A9258A46E97FF8B2CAC7910577862C14F2C524': stem.directory.Fallback( address = '193.171.202.146', @@ -147,7 +185,7 @@ class TestFallback(unittest.TestCase): nickname = None, has_extrainfo = False, orport_v6 = None, - header = header, + header = HEADER, ), }
@@ -171,48 +209,10 @@ class TestFallback(unittest.TestCase): }
with tempfile.NamedTemporaryFile(prefix = 'fallbacks.') as tmp: - stem.directory.Fallback._write(expected, 'abc', 'def', header, tmp.name) + stem.directory.Fallback._write(expected, 'abc', 'def', HEADER, tmp.name)
conf = stem.util.conf.Config() conf.load(tmp.name) self.assertEqual(excepted_config, dict(conf))
self.assertEqual(expected, stem.directory.Fallback.from_cache(tmp.name)) - - @patch(URL_OPEN, Mock(return_value = io.BytesIO(b''))) - def test_from_remote_empty(self): - self.assertRaisesRegexp(IOError, 'did not have any content', stem.directory.Fallback.from_remote) - - @patch(URL_OPEN, Mock(return_value = io.BytesIO(b'\n'.join(FALLBACK_DIR_CONTENT.splitlines()[1:])))) - def test_from_remote_no_header(self): - self.assertRaisesRegexp(IOError, 'does not have a type field indicating it is fallback directory metadata', stem.directory.Fallback.from_remote) - - @patch(URL_OPEN, Mock(return_value = io.BytesIO(FALLBACK_DIR_CONTENT.replace(b'version=2.0.0', b'version')))) - def test_from_remote_malformed_header(self): - self.assertRaisesRegexp(IOError, 'Malformed fallback directory header line: /* version */', stem.directory.Fallback.from_remote) - - def test_from_str(self): - expected = stem.directory.Fallback( - address = '5.9.110.236', - or_port = 9001, - dir_port = 9030, - fingerprint = '0756B7CD4DFC8182BE23143FAC0642F515182CEB', - nickname = 'rueckgrat', - has_extrainfo = True, - orport_v6 = ('2a01:4f8:162:51e2::2', 9001), - ) - - self.assertEqual(expected, stem.directory.Fallback._from_str(FALLBACK_ENTRY)) - - def test_from_str_malformed(self): - test_values = { - FALLBACK_ENTRY.replace(b'id=0756B7CD4DFC8182BE23143FAC0642F515182CEB', b''): 'Malformed fallback address line:', - FALLBACK_ENTRY.replace(b'5.9.110.236', b'5.9.110'): '0756B7CD4DFC8182BE23143FAC0642F515182CEB has an invalid IPv4 address: 5.9.110', - FALLBACK_ENTRY.replace(b':9030', b':7814713228'): '0756B7CD4DFC8182BE23143FAC0642F515182CEB has an invalid dir_port: 7814713228', - FALLBACK_ENTRY.replace(b'orport=9001', b'orport=7814713228'): '0756B7CD4DFC8182BE23143FAC0642F515182CEB has an invalid or_port: 7814713228', - FALLBACK_ENTRY.replace(b'ipv6=[2a01', b'ipv6=[:::'): '0756B7CD4DFC8182BE23143FAC0642F515182CEB has an invalid IPv6 address: ::::4f8:162:51e2::2', - FALLBACK_ENTRY.replace(b'nickname=rueckgrat', b'nickname=invalid~nickname'): '0756B7CD4DFC8182BE23143FAC0642F515182CEB has an invalid nickname: invalid~nickname', - } - - for entry, expected in test_values.items(): - self.assertRaisesRegexp(ValueError, expected, stem.directory.Fallback._from_str, entry)
tor-commits@lists.torproject.org