commit 5245c052ba5cd9cd80d45f7bbda4eade2425d8ba Author: Damian Johnson atagar@torproject.org Date: Mon May 1 14:08:18 2017 -0700
RouterStatusEntry creation --- stem/descriptor/router_status_entry.py | 28 +++++ test/mocking.py | 80 --------------- test/unit/descriptor/networkstatus/document_v3.py | 26 +++-- test/unit/descriptor/router_status_entry.py | 118 +++++++++------------- test/unit/response/events.py | 7 +- test/unit/tutorial.py | 7 +- test/unit/tutorial_examples.py | 18 ++-- 7 files changed, 101 insertions(+), 183 deletions(-)
diff --git a/stem/descriptor/router_status_entry.py b/stem/descriptor/router_status_entry.py index 129f6f7..973f833 100644 --- a/stem/descriptor/router_status_entry.py +++ b/stem/descriptor/router_status_entry.py @@ -29,6 +29,7 @@ import stem.util.str_tools from stem.descriptor import ( KEYWORD_LINE, Descriptor, + _descriptor_content, _value, _values, _descriptor_components, @@ -36,6 +37,21 @@ from stem.descriptor import ( _read_until_keywords, )
+ROUTER_STATUS_ENTRY_V2_HEADER = ( + ('r', 'caerSidi p1aag7VwarGxqctS7/fS0y5FU+s oQZFLYe9e4A7bOkWKR7TaNxb0JE 2012-08-06 11:19:31 71.35.150.29 9001 0'), +) + +ROUTER_STATUS_ENTRY_V3_HEADER = ( + ('r', 'caerSidi p1aag7VwarGxqctS7/fS0y5FU+s oQZFLYe9e4A7bOkWKR7TaNxb0JE 2012-08-06 11:19:31 71.35.150.29 9001 0'), + ('s', 'Fast Named Running Stable Valid'), +) + +ROUTER_STATUS_ENTRY_MICRO_V3_HEADER = ( + ('r', 'Konata ARIJF2zbqirB9IwsW0mQznccWww 2012-09-24 13:40:40 69.64.48.168 9001 9030'), + ('m', 'aiUklwBrua82obG5AsTX+iEpkjQA2+AQHxZ7GwMfY70'), + ('s', 'Fast Guard HSDir Named Running Stable V2Dir Valid'), +) + _parse_pr_line = _parse_protocol_line('pr', 'protocols')
@@ -511,6 +527,10 @@ class RouterStatusEntryV2(RouterStatusEntry): 'digest': (None, _parse_r_line), })
+ @classmethod + def content(cls, attr = None, exclude = ()): + return _descriptor_content(attr, exclude, ROUTER_STATUS_ENTRY_V2_HEADER) + def _name(self, is_plural = False): return 'Router status entries (v2)' if is_plural else 'Router status entry (v2)'
@@ -604,6 +624,10 @@ class RouterStatusEntryV3(RouterStatusEntry): 'm': _parse_m_line, })
+ @classmethod + def content(cls, attr = None, exclude = ()): + return _descriptor_content(attr, exclude, ROUTER_STATUS_ENTRY_V3_HEADER) + def _name(self, is_plural = False): return 'Router status entries (v3)' if is_plural else 'Router status entry (v3)'
@@ -673,6 +697,10 @@ class RouterStatusEntryMicroV3(RouterStatusEntry): 'pr': _parse_pr_line, })
+ @classmethod + def content(cls, attr = None, exclude = ()): + return _descriptor_content(attr, exclude, ROUTER_STATUS_ENTRY_MICRO_V3_HEADER) + def _name(self, is_plural = False): return 'Router status entries (micro v3)' if is_plural else 'Router status entry (micro v3)'
diff --git a/test/mocking.py b/test/mocking.py index 09d3631..c88784a 100644 --- a/test/mocking.py +++ b/test/mocking.py @@ -18,11 +18,6 @@ Helper functions for creating mock objects. get_key_certificate - KeyCertificate get_network_status_document_v2 - NetworkStatusDocumentV2 get_network_status_document_v3 - NetworkStatusDocumentV3 - - stem.descriptor.router_status_entry - get_router_status_entry_v2 - RouterStatusEntryV2 - get_router_status_entry_v3 - RouterStatusEntryV3 - get_router_status_entry_micro_v3 - RouterStatusEntryMicroV3 """
import hashlib @@ -58,21 +53,6 @@ DOC_SIG = stem.descriptor.networkstatus.DocumentSignature( 'BF112F1C6D5543CFD0A32215ACABD4197B5279AD', '-----BEGIN SIGNATURE-----%s-----END SIGNATURE-----' % CRYPTO_BLOB)
-ROUTER_STATUS_ENTRY_V2_HEADER = ( - ('r', 'caerSidi p1aag7VwarGxqctS7/fS0y5FU+s oQZFLYe9e4A7bOkWKR7TaNxb0JE 2012-08-06 11:19:31 71.35.150.29 9001 0'), -) - -ROUTER_STATUS_ENTRY_V3_HEADER = ( - ('r', 'caerSidi p1aag7VwarGxqctS7/fS0y5FU+s oQZFLYe9e4A7bOkWKR7TaNxb0JE 2012-08-06 11:19:31 71.35.150.29 9001 0'), - ('s', 'Fast Named Running Stable Valid'), -) - -ROUTER_STATUS_ENTRY_MICRO_V3_HEADER = ( - ('r', 'Konata ARIJF2zbqirB9IwsW0mQznccWww 2012-09-24 13:40:40 69.64.48.168 9001 9030'), - ('m', 'aiUklwBrua82obG5AsTX+iEpkjQA2+AQHxZ7GwMfY70'), - ('s', 'Fast Guard HSDir Named Running Stable V2Dir Valid'), -) - AUTHORITY_HEADER = ( ('dir-source', 'turtles 27B6B5996C426270A5C95488AA5BCEB6BCC86956 no.place.com 76.73.17.194 9030 9090'), ('contact', 'Mike Perry <email>'), @@ -287,66 +267,6 @@ def _get_descriptor_content(attr = None, exclude = (), header_template = (), foo return stem.util.str_tools._to_bytes('\n'.join(header_content + remainder + footer_content))
-def get_router_status_entry_v2(attr = None, exclude = (), content = False): - """ - Provides the descriptor content for... - stem.descriptor.router_status_entry.RouterStatusEntryV2 - - :param dict attr: keyword/value mappings to be included in the descriptor - :param list exclude: mandatory keywords to exclude from the descriptor - :param bool content: provides the str content of the descriptor rather than the class if True - - :returns: RouterStatusEntryV2 for the requested descriptor content - """ - - desc_content = _get_descriptor_content(attr, exclude, ROUTER_STATUS_ENTRY_V2_HEADER) - - if content: - return desc_content - else: - return stem.descriptor.router_status_entry.RouterStatusEntryV2(desc_content, validate = True) - - -def get_router_status_entry_v3(attr = None, exclude = (), content = False): - """ - Provides the descriptor content for... - stem.descriptor.router_status_entry.RouterStatusEntryV3 - - :param dict attr: keyword/value mappings to be included in the descriptor - :param list exclude: mandatory keywords to exclude from the descriptor - :param bool content: provides the str content of the descriptor rather than the class if True - - :returns: RouterStatusEntryV3 for the requested descriptor content - """ - - desc_content = _get_descriptor_content(attr, exclude, ROUTER_STATUS_ENTRY_V3_HEADER) - - if content: - return desc_content - else: - return stem.descriptor.router_status_entry.RouterStatusEntryV3(desc_content, validate = True) - - -def get_router_status_entry_micro_v3(attr = None, exclude = (), content = False): - """ - Provides the descriptor content for... - stem.descriptor.router_status_entry.RouterStatusEntryMicroV3 - - :param dict attr: keyword/value mappings to be included in the descriptor - :param list exclude: mandatory keywords to exclude from the descriptor - :param bool content: provides the str content of the descriptor rather than the class if True - - :returns: RouterStatusEntryMicroV3 for the requested descriptor content - """ - - desc_content = _get_descriptor_content(attr, exclude, ROUTER_STATUS_ENTRY_MICRO_V3_HEADER) - - if content: - return desc_content - else: - return stem.descriptor.router_status_entry.RouterStatusEntryMicroV3(desc_content, validate = True) - - def get_directory_authority(attr = None, exclude = (), is_vote = False, content = False): """ Provides the descriptor content for... diff --git a/test/unit/descriptor/networkstatus/document_v3.py b/test/unit/descriptor/networkstatus/document_v3.py index 6a2e784..d6ea34e 100644 --- a/test/unit/descriptor/networkstatus/document_v3.py +++ b/test/unit/descriptor/networkstatus/document_v3.py @@ -29,8 +29,6 @@ from stem.descriptor.router_status_entry import ( )
from test.mocking import ( - get_router_status_entry_v3, - get_router_status_entry_micro_v3, get_directory_authority, get_network_status_document_v3, DOC_SIG, @@ -400,8 +398,8 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w=
# makes a consensus with a couple routers, both with the same nickname
- entry1 = get_router_status_entry_v3({'s': 'Fast'}) - entry2 = get_router_status_entry_v3({'s': 'Valid'}) + entry1 = RouterStatusEntryV3.create({'s': 'Fast'}) + entry2 = RouterStatusEntryV3.create({'s': 'Valid'}) content = get_network_status_document_v3(routers = (entry1, entry2), content = True)
# first example: parsing via the NetworkStatusDocumentV3 constructor @@ -428,8 +426,8 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w= # Simple sanity check that they provide the right type, and that the # document includes or excludes the router status entries as appropriate.
- entry1 = get_router_status_entry_v3({'s': 'Fast'}) - entry2 = get_router_status_entry_v3({ + entry1 = RouterStatusEntryV3.create({'s': 'Fast'}) + entry2 = RouterStatusEntryV3.create({ 'r': 'Nightfae AWt0XNId/OU2xX5xs5hVtDc5Mes 6873oEfM7fFIbxYtwllw9GPDwkA 2013-02-20 11:12:27 85.177.66.233 9001 9030', 's': 'Valid', }) @@ -451,8 +449,8 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w= Try parsing a document via the _parse_file() function. """
- entry1 = get_router_status_entry_v3({'s': 'Fast'}) - entry2 = get_router_status_entry_v3({'s': 'Valid'}) + entry1 = RouterStatusEntryV3.create({'s': 'Fast'}) + entry2 = RouterStatusEntryV3.create({'s': 'Valid'}) content = get_network_status_document_v3(routers = (entry1, entry2), content = True)
# the document that the entries refer to should actually be the minimal @@ -1093,8 +1091,8 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w= document. """
- entry1 = get_router_status_entry_v3({'s': 'Fast'}) - entry2 = get_router_status_entry_v3({ + entry1 = RouterStatusEntryV3.create({'s': 'Fast'}) + entry2 = RouterStatusEntryV3.create({ 'r': 'Nightfae AWt0XNId/OU2xX5xs5hVtDc5Mes 6873oEfM7fFIbxYtwllw9GPDwkA 2013-02-20 11:12:27 85.177.66.233 9001 9030', 's': 'Valid', }) @@ -1106,7 +1104,7 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w=
# try with an invalid RouterStatusEntry
- entry3 = RouterStatusEntryV3(get_router_status_entry_v3({'r': 'ugabuga'}, content = True), False) + entry3 = RouterStatusEntryV3(RouterStatusEntryV3.content({'r': 'ugabuga'}), False) content = get_network_status_document_v3(routers = (entry3,), content = True)
self.assertRaises(ValueError, NetworkStatusDocumentV3, content, True) @@ -1127,8 +1125,8 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w= document. """
- entry1 = get_router_status_entry_micro_v3({'s': 'Fast'}) - entry2 = get_router_status_entry_micro_v3({ + entry1 = RouterStatusEntryMicroV3.create({'s': 'Fast'}) + entry2 = RouterStatusEntryMicroV3.create({ 'r': 'tornodeviennasil AcWxDFxrHetHYS5m6/MVt8ZN6AM 2013-03-13 22:09:13 78.142.142.246 443 80', 's': 'Valid', }) @@ -1140,7 +1138,7 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w=
# try with an invalid RouterStatusEntry
- entry3 = RouterStatusEntryMicroV3(get_router_status_entry_micro_v3({'r': 'ugabuga'}, content = True), False) + entry3 = RouterStatusEntryMicroV3(RouterStatusEntryMicroV3.content({'r': 'ugabuga'}), False)
content = get_network_status_document_v3({'network-status-version': '3 microdesc'}, routers = (entry3,), content = True) self.assertRaises(ValueError, NetworkStatusDocumentV3, content, True) diff --git a/test/unit/descriptor/router_status_entry.py b/test/unit/descriptor/router_status_entry.py index 43bcaee..37d763e 100644 --- a/test/unit/descriptor/router_status_entry.py +++ b/test/unit/descriptor/router_status_entry.py @@ -3,22 +3,27 @@ Unit tests for stem.descriptor.router_status_entry. """
import datetime +import functools import unittest
import stem.descriptor
from stem import Flag -from stem.descriptor.router_status_entry import RouterStatusEntryV3, _base64_to_hex from stem.exit_policy import MicroExitPolicy from stem.version import Version
-from test.unit.descriptor import get_resource +from test.unit.descriptor import ( + get_resource, + base_expect_invalid_attr, + base_expect_invalid_attr_for_text, +)
-from test.mocking import ( - get_router_status_entry_v2, - get_router_status_entry_v3, - get_router_status_entry_micro_v3, +from stem.descriptor.router_status_entry import ( ROUTER_STATUS_ENTRY_V3_HEADER, + RouterStatusEntryV2, + RouterStatusEntryV3, + RouterStatusEntryMicroV3, + _base64_to_hex, )
ENTRY_WITHOUT_ED25519 = """\ @@ -47,6 +52,9 @@ m 18,19,20 sha256=AkZH3gIvz3wunsroqh5izBJizdYuR7kn2oVbsvqgML8 m 21 sha256=AVp41YVxKEJCaoEf0+77Cdvyw5YgpyDXdob0+LSv/pE """
+expect_invalid_attr = functools.partial(base_expect_invalid_attr, RouterStatusEntryV3, 'nickname', 'caerSidi') +expect_invalid_attr_for_text = functools.partial(base_expect_invalid_attr_for_text, RouterStatusEntryV3, 'nickname', 'caerSidi') +
def vote_document(): class Stub(object): @@ -86,7 +94,7 @@ class TestRouterStatusEntry(unittest.TestCase): Parses a minimal v2 router status entry. """
- entry = get_router_status_entry_v2() + entry = RouterStatusEntryV2.create()
self.assertEqual(None, entry.document) self.assertEqual('caerSidi', entry.nickname) @@ -106,7 +114,7 @@ class TestRouterStatusEntry(unittest.TestCase): Parses a minimal v3 router status entry. """
- entry = get_router_status_entry_v3() + entry = RouterStatusEntryV3.create()
expected_flags = set([Flag.FAST, Flag.NAMED, Flag.RUNNING, Flag.STABLE, Flag.VALID]) self.assertEqual(None, entry.document) @@ -135,7 +143,7 @@ class TestRouterStatusEntry(unittest.TestCase): Parses a minimal microdescriptor v3 router status entry. """
- entry = get_router_status_entry_micro_v3() + entry = RouterStatusEntryMicroV3.create()
expected_flags = set([Flag.FAST, Flag.GUARD, Flag.HSDIR, Flag.NAMED, Flag.RUNNING, Flag.STABLE, Flag.V2DIR, Flag.VALID]) self.assertEqual(None, entry.document) @@ -222,21 +230,16 @@ class TestRouterStatusEntry(unittest.TestCase): Parses a router status entry that's missing fields. """
- content = get_router_status_entry_v3(exclude = ('r', 's'), content = True) - self._expect_invalid_attr(content, 'address') - - content = get_router_status_entry_v3(exclude = ('r',), content = True) - self._expect_invalid_attr(content, 'address') - - content = get_router_status_entry_v3(exclude = ('s',), content = True) - self._expect_invalid_attr(content, 'flags') + expect_invalid_attr_for_text(self, RouterStatusEntryV3.content(exclude = ('r', 's')), 'address') + expect_invalid_attr_for_text(self, RouterStatusEntryV3.content(exclude = ('r',)), 'address') + expect_invalid_attr_for_text(self, RouterStatusEntryV3.content(exclude = ('s',)), 'flags')
def test_unrecognized_lines(self): """ Parses a router status entry with new keywords. """
- entry = get_router_status_entry_v3({'z': 'New tor feature: sparkly unicorns!'}) + entry = RouterStatusEntryV3.create({'z': 'New tor feature: sparkly unicorns!'}) self.assertEqual(['z New tor feature: sparkly unicorns!'], entry.get_unrecognized_lines())
def test_proceeding_line(self): @@ -244,7 +247,7 @@ class TestRouterStatusEntry(unittest.TestCase): Includes content prior to the 'r' line. """
- content = b'z some stuff\n' + get_router_status_entry_v3(content = True) + content = b'z some stuff\n' + RouterStatusEntryV3.content() self.assertRaises(ValueError, RouterStatusEntryV3, content, True) self.assertEqual(['z some stuff'], RouterStatusEntryV3(content, False).get_unrecognized_lines())
@@ -253,7 +256,7 @@ class TestRouterStatusEntry(unittest.TestCase): Includes blank lines, which should be ignored. """
- content = get_router_status_entry_v3(content = True) + b'\n\nv Tor 0.2.2.35\n\n' + content = RouterStatusEntryV3.content() + b'\n\nv Tor 0.2.2.35\n\n' entry = RouterStatusEntryV3(content) self.assertEqual('Tor 0.2.2.35', entry.version_line)
@@ -262,7 +265,7 @@ class TestRouterStatusEntry(unittest.TestCase): Duplicates linesin the entry. """
- lines = get_router_status_entry_v3(content = True).split(b'\n') + lines = RouterStatusEntryV3.content().split(b'\n')
for index, duplicate_line in enumerate(lines): content = b'\n'.join(lines[:index] + [duplicate_line] + lines[index:]) @@ -291,9 +294,7 @@ class TestRouterStatusEntry(unittest.TestCase): test_components = [comp[1] for comp in components] test_components.remove(value) r_line = ' '.join(test_components) - - content = get_router_status_entry_v3({'r': r_line}, content = True) - self._expect_invalid_attr(content, attr) + expect_invalid_attr(self, {'r': r_line}, attr)
def test_malformed_nickname(self): """ @@ -308,7 +309,6 @@ class TestRouterStatusEntry(unittest.TestCase):
for value in test_values: r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1].replace('caerSidi', value) - content = get_router_status_entry_v3({'r': r_line}, content = True)
# TODO: Initial whitespace is consumed as part of the keyword/value # divider. This is a bug in the case of V3 router status entries, but @@ -323,7 +323,7 @@ class TestRouterStatusEntry(unittest.TestCase): if value == '': value = None
- self._expect_invalid_attr(content, 'nickname') + expect_invalid_attr(self, {'r': r_line}, 'nickname')
def test_malformed_fingerprint(self): """ @@ -338,8 +338,7 @@ class TestRouterStatusEntry(unittest.TestCase):
for value in test_values: r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1].replace('p1aag7VwarGxqctS7/fS0y5FU+s', value) - content = get_router_status_entry_v3({'r': r_line}, content = True) - self._expect_invalid_attr(content, 'fingerprint') + expect_invalid_attr(self, {'r': r_line}, 'fingerprint')
def test_malformed_published_date(self): """ @@ -364,8 +363,7 @@ class TestRouterStatusEntry(unittest.TestCase):
for value in test_values: r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1].replace('2012-08-06 11:19:31', value) - content = get_router_status_entry_v3({'r': r_line}, content = True) - self._expect_invalid_attr(content, 'published') + expect_invalid_attr(self, {'r': r_line}, 'published')
def test_malformed_address(self): """ @@ -382,8 +380,7 @@ class TestRouterStatusEntry(unittest.TestCase):
for value in test_values: r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1].replace('71.35.150.29', value) - content = get_router_status_entry_v3({'r': r_line}, content = True) - self._expect_invalid_attr(content, 'address') + expect_invalid_attr(self, {'r': r_line}, 'address')
def test_malformed_port(self): """ @@ -412,9 +409,7 @@ class TestRouterStatusEntry(unittest.TestCase): r_line = r_line[:-1] + value
attr = 'or_port' if include_or_port else 'dir_port' - - content = get_router_status_entry_v3({'r': r_line}, content = True) - self._expect_invalid_attr(content, attr) + expect_invalid_attr(self, {'r': r_line}, attr)
def test_ipv6_addresses(self): """ @@ -427,12 +422,12 @@ class TestRouterStatusEntry(unittest.TestCase): }
for a_line, expected in test_values.items(): - entry = get_router_status_entry_v3({'a': a_line}) + entry = RouterStatusEntryV3.create({'a': a_line}) self.assertEqual(expected, entry.or_addresses)
# includes multiple 'a' lines
- content = get_router_status_entry_v3(content = True) + content = RouterStatusEntryV3.content() content += b'\na [2607:fcd0:daaa:101::602c:bd62]:443' content += b'\na [1148:fcd0:daaa:101::602c:bd62]:80'
@@ -452,8 +447,7 @@ class TestRouterStatusEntry(unittest.TestCase): )
for a_line in test_values: - content = get_router_status_entry_v3({'a': a_line}, content = True) - self._expect_invalid_attr(content, expected_value = {}) + expect_invalid_attr(self, {'a': a_line}, expected_value = {})
def test_flags(self): """ @@ -468,7 +462,7 @@ class TestRouterStatusEntry(unittest.TestCase): }
for s_line, expected in test_values.items(): - entry = get_router_status_entry_v3({'s': s_line}) + entry = RouterStatusEntryV3.create({'s': s_line}) self.assertEqual(expected, entry.flags)
# tries some invalid inputs @@ -479,11 +473,10 @@ class TestRouterStatusEntry(unittest.TestCase): }
for s_line, expected in test_values.items(): - content = get_router_status_entry_v3({'s': s_line}, content = True) - self._expect_invalid_attr(content, 'flags', expected) + expect_invalid_attr(self, {'s': s_line}, 'flags', expected)
def test_protocols(self): - desc = get_router_status_entry_v3({'pr': 'Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=1-4 LinkAuth=1 Microdesc=1 Relay=1-2'}) + desc = RouterStatusEntryV3.create({'pr': 'Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=1-4 LinkAuth=1 Microdesc=1 Relay=1-2'}) self.assertEqual(10, len(desc.protocols))
def test_versions(self): @@ -499,13 +492,12 @@ class TestRouterStatusEntry(unittest.TestCase): }
for v_line, expected in test_values.items(): - entry = get_router_status_entry_v3({'v': v_line}) + entry = RouterStatusEntryV3.create({'v': v_line}) self.assertEqual(expected, entry.version) self.assertEqual(v_line, entry.version_line)
# tries an invalid input - content = get_router_status_entry_v3({'v': 'Tor ugabuga'}, content = True) - self._expect_invalid_attr(content, 'version') + expect_invalid_attr(self, {'v': 'Tor ugabuga'}, 'version')
def test_bandwidth(self): """ @@ -521,7 +513,7 @@ class TestRouterStatusEntry(unittest.TestCase): }
for w_line, expected in test_values.items(): - entry = get_router_status_entry_v3({'w': w_line}) + entry = RouterStatusEntryV3.create({'w': w_line}) self.assertEqual(expected[0], entry.bandwidth) self.assertEqual(expected[1], entry.measured) self.assertEqual(expected[2], entry.is_unmeasured) @@ -547,8 +539,7 @@ class TestRouterStatusEntry(unittest.TestCase): )
for w_line in test_values: - content = get_router_status_entry_v3({'w': w_line}, content = True) - self._expect_invalid_attr(content) + expect_invalid_attr(self, {'w': w_line})
def test_exit_policy(self): """ @@ -561,7 +552,7 @@ class TestRouterStatusEntry(unittest.TestCase): }
for p_line, expected in test_values.items(): - entry = get_router_status_entry_v3({'p': p_line}) + entry = RouterStatusEntryV3.create({'p': p_line}) self.assertEqual(expected, entry.exit_policy)
# tries some invalid inputs @@ -573,8 +564,7 @@ class TestRouterStatusEntry(unittest.TestCase): )
for p_line in test_values: - content = get_router_status_entry_v3({'p': p_line}, content = True) - self._expect_invalid_attr(content, 'exit_policy') + expect_invalid_attr(self, {'p': p_line}, 'exit_policy')
def test_microdescriptor_hashes(self): """ @@ -591,13 +581,13 @@ class TestRouterStatusEntry(unittest.TestCase): }
for m_line, expected in test_values.items(): - content = get_router_status_entry_v3({'m': m_line}, content = True) + content = RouterStatusEntryV3.content({'m': m_line}) entry = RouterStatusEntryV3(content, document = vote_document()) self.assertEqual(expected, entry.microdescriptor_hashes)
# try with multiple 'm' lines
- content = get_router_status_entry_v3(content = True) + content = RouterStatusEntryV3.content() content += b'\nm 11,12 sha256=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs' content += b'\nm 31,32 sha512=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'
@@ -610,8 +600,7 @@ class TestRouterStatusEntry(unittest.TestCase): self.assertEqual(expected, entry.microdescriptor_hashes)
# try without a document - content = get_router_status_entry_v3({'m': '8,9,10,11,12'}, content = True) - self._expect_invalid_attr(content, 'microdescriptor_hashes', expected_value = []) + expect_invalid_attr(self, {'m': '8,9,10,11,12'}, 'microdescriptor_hashes', expected_value = [])
# tries some invalid inputs test_values = ( @@ -621,7 +610,7 @@ class TestRouterStatusEntry(unittest.TestCase): )
for m_line in test_values: - content = get_router_status_entry_v3({'m': m_line}, content = True) + content = RouterStatusEntryV3.content({'m': m_line}) self.assertRaises(ValueError, RouterStatusEntryV3, content, True, vote_document())
def test_with_carriage_returns(self): @@ -638,18 +627,3 @@ class TestRouterStatusEntry(unittest.TestCase):
router = next(descriptors) self.assertEqual([Flag.FAST, Flag.RUNNING, Flag.STABLE, Flag.VALID], router.flags) - - def _expect_invalid_attr(self, content, attr = None, expected_value = None): - """ - Asserts that construction will fail due to content having a malformed - attribute. If an attr is provided then we check that it matches an expected - value when we're constructed without validation. - """ - - self.assertRaises(ValueError, RouterStatusEntryV3, content, True) - entry = RouterStatusEntryV3(content, False) - - if attr: - self.assertEqual(expected_value, getattr(entry, attr)) - else: - self.assertEqual('caerSidi', entry.nickname) diff --git a/test/unit/response/events.py b/test/unit/response/events.py index 8a95156..6023db6 100644 --- a/test/unit/response/events.py +++ b/test/unit/response/events.py @@ -11,6 +11,7 @@ import stem.response.events import stem.util.log
from stem import * # enums and exceptions +from stem.descriptor.router_status_entry import RouterStatusEntryV3 from test import mocking
try: @@ -934,12 +935,12 @@ class TestEvents(unittest.TestCase): def test_new_consensus_event(self): expected_desc = []
- expected_desc.append(mocking.get_router_status_entry_v3({ + expected_desc.append(RouterStatusEntryV3.create({ 'r': 'Beaver /96bKo4soysolMgKn5Hex2nyFSY pAJH9dSBp/CG6sPhhVY/5bLaVPM 2012-12-02 22:02:45 77.223.43.54 9001 0', 's': 'Fast Named Running Stable Valid', }))
- expected_desc.append(mocking.get_router_status_entry_v3({ + expected_desc.append(RouterStatusEntryV3.create({ 'r': 'Unnamed /+fJRWjmIGNAL2C5rRZHq3R91tA 7AnpZjfdBpYzXnMNm+w1bTsFF6Y 2012-12-02 17:51:10 91.121.184.87 9001 0', 's': 'Fast Guard Running Stable Valid', })) @@ -950,7 +951,7 @@ class TestEvents(unittest.TestCase): self.assertEqual(expected_desc, event.desc)
def test_ns_event(self): - expected_desc = mocking.get_router_status_entry_v3({ + expected_desc = RouterStatusEntryV3.create({ 'r': 'whnetz dbBxYcJriTTrcxsuy4PUZcMRwCA VStM7KAIH/mXXoGDUpoGB1OXufg 2012-12-02 21:03:56 141.70.120.13 9001 9030', 's': 'Fast HSDir Named Stable V2Dir Valid', }) diff --git a/test/unit/tutorial.py b/test/unit/tutorial.py index a404b42..48d0abb 100644 --- a/test/unit/tutorial.py +++ b/test/unit/tutorial.py @@ -10,6 +10,7 @@ import stem.descriptor.remote from stem.control import Controller from stem.descriptor.reader import DescriptorReader from stem.descriptor.server_descriptor import RelayDescriptor +from stem.descriptor.router_status_entry import RouterStatusEntryV2, RouterStatusEntryV3 from test import mocking from test.unit import exec_documentation_example
@@ -127,7 +128,7 @@ class TestTutorial(unittest.TestCase): @patch('sys.stdout', new_callable = StringIO) @patch('stem.descriptor.remote.DescriptorDownloader') def test_mirror_mirror_on_the_wall_1(self, downloader_mock, stdout_mock): - downloader_mock().get_consensus().run.return_value = [mocking.get_router_status_entry_v2()] + downloader_mock().get_consensus().run.return_value = [RouterStatusEntryV2.create()]
exec_documentation_example('current_descriptors.py') self.assertEqual('found relay caerSidi (A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB)\n', stdout_mock.getvalue()) @@ -136,7 +137,7 @@ class TestTutorial(unittest.TestCase): @patch('stem.control.Controller.from_port', spec = Controller) def test_mirror_mirror_on_the_wall_2(self, from_port_mock, stdout_mock): controller = from_port_mock().__enter__() - controller.get_network_statuses.return_value = [mocking.get_router_status_entry_v2()] + controller.get_network_statuses.return_value = [RouterStatusEntryV2.create()]
exec_documentation_example('descriptor_from_tor_control_socket.py') self.assertEqual('found relay caerSidi (A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB)\n', stdout_mock.getvalue()) @@ -151,7 +152,7 @@ class TestTutorial(unittest.TestCase): print('found relay %s (%s)' % (desc.nickname, desc.fingerprint))
test_file = io.BytesIO(mocking.get_network_status_document_v3( - routers = [mocking.get_router_status_entry_v3()], + routers = [RouterStatusEntryV3.create()], content = True, ))
diff --git a/test/unit/tutorial_examples.py b/test/unit/tutorial_examples.py index 267fd3d..b3ac813 100644 --- a/test/unit/tutorial_examples.py +++ b/test/unit/tutorial_examples.py @@ -19,16 +19,12 @@ from stem.control import Controller from stem.util import str_type from stem.descriptor.remote import DIRECTORY_AUTHORITIES from stem.descriptor.server_descriptor import RelayDescriptor +from stem.descriptor.router_status_entry import ROUTER_STATUS_ENTRY_V3_HEADER, RouterStatusEntryV3
from test import mocking +from test.mocking import get_network_status_document_v3 from test.unit import exec_documentation_example
-from test.mocking import ( - get_router_status_entry_v3, - ROUTER_STATUS_ENTRY_V3_HEADER, - get_network_status_document_v3, -) - try: # added in python 3.3 from unittest.mock import Mock, patch @@ -130,9 +126,9 @@ def _get_router_status(address = None, port = None, nickname = None, fingerprint r_line = r_line.replace('p1aag7VwarGxqctS7/fS0y5FU+s', fingerprint_base64)
if s_line: - return get_router_status_entry_v3({'r': r_line, 's': s_line}) + return RouterStatusEntryV3.create({'r': r_line, 's': s_line}) else: - return get_router_status_entry_v3({'r': r_line}) + return RouterStatusEntryV3.create({'r': r_line})
class TestTutorialExamples(unittest.TestCase): @@ -299,8 +295,8 @@ class TestTutorialExamples(unittest.TestCase): directory_values[0].address = '131.188.40.189' get_authorities_mock().values.return_value = directory_values
- entry_with_measurement = get_router_status_entry_v3({'w': 'Bandwidth=1 Measured=1'}) - entry_without_measurement = get_router_status_entry_v3() + entry_with_measurement = RouterStatusEntryV3.create({'w': 'Bandwidth=1 Measured=1'}) + entry_without_measurement = RouterStatusEntryV3.create()
query1 = Mock() query1.download_url = 'http://131.188.40.189:80/tor/status-vote/current/authority' @@ -336,7 +332,7 @@ class TestTutorialExamples(unittest.TestCase): for fingerprint, relay in consensus.routers.items(): print('%s: %s' % (fingerprint, relay.nickname))
- network_status = get_network_status_document_v3(routers = (get_router_status_entry_v3(),)) + network_status = get_network_status_document_v3(routers = (RouterStatusEntryV3.create(),)) query_mock().run.return_value = [network_status] parse_file_mock.return_value = itertools.cycle([network_status])