commit 13224f9ecda24fd8b56af6a3f9f8a4a897191a61 Author: Damian Johnson atagar@torproject.org Date: Mon May 1 11:49:08 2017 -0700
expect_invalid_attr() testing helper
Four unit test modules define their own nearly identical _expect_invalid_attr() helper. Creating a unified one they can share. Presently I can only swap two of the modules over because it requires create(). I'll migrate the rest as we add it. --- test/unit/descriptor/__init__.py | 25 ++++++++ test/unit/descriptor/extrainfo_descriptor.py | 90 +++++++++------------------- test/unit/descriptor/server_descriptor.py | 60 +++++++------------ 3 files changed, 76 insertions(+), 99 deletions(-)
diff --git a/test/unit/descriptor/__init__.py b/test/unit/descriptor/__init__.py index b7696ac..cd35ae1 100644 --- a/test/unit/descriptor/__init__.py +++ b/test/unit/descriptor/__init__.py @@ -23,3 +23,28 @@ def get_resource(filename): """
return os.path.join(DESCRIPTOR_TEST_DATA, filename) + + +def base_expect_invalid_attr(cls, default_attr, default_value, test, desc_attrs, attr = None, expected_value = None): + return base_expect_invalid_attr_for_text(cls, default_attr, default_value, test, cls.content(desc_attrs), attr, expected_value) + + +def base_expect_invalid_attr_for_text(cls, default_attr, default_value, test, desc_text, attr = None, expected_value = None): + """ + Asserts that construction will fail due to desc_text having a malformed + attribute. If an attr is provided then we check that it matches an expected + value when we're constructed without validation. + """ + + test.assertRaises(ValueError, cls, desc_text, True) + desc = cls(desc_text, validate = False) + + if attr: + # check that the invalid attribute matches the expected value when + # constructed without validation + + test.assertEqual(expected_value, getattr(desc, attr)) + elif default_attr and default_value: + test.assertEqual(default_value, getattr(desc, default_attr)) # check a default attribute + + return desc diff --git a/test/unit/descriptor/extrainfo_descriptor.py b/test/unit/descriptor/extrainfo_descriptor.py index 2269000..a59d0f0 100644 --- a/test/unit/descriptor/extrainfo_descriptor.py +++ b/test/unit/descriptor/extrainfo_descriptor.py @@ -3,6 +3,7 @@ Unit tests for stem.descriptor.extrainfo_descriptor. """
import datetime +import functools import re import unittest
@@ -15,9 +16,14 @@ from stem.descriptor.extrainfo_descriptor import ( DirStat, )
-from test.mocking import CRYPTO_BLOB +from test.unit.descriptor import ( + get_resource, + base_expect_invalid_attr, + base_expect_invalid_attr_for_text, +)
-from test.unit.descriptor import get_resource +expect_invalid_attr = functools.partial(base_expect_invalid_attr, RelayExtraInfoDescriptor, 'nickname', 'ninja') +expect_invalid_attr_for_text = functools.partial(base_expect_invalid_attr_for_text, RelayExtraInfoDescriptor, 'nickname', 'ninja')
class TestExtraInfoDescriptor(unittest.TestCase): @@ -191,7 +197,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw desc = RelayExtraInfoDescriptor.create() self.assertEqual('ninja', desc.nickname) self.assertEqual('B2289C3EAB83ECD6EB916A2F481A02E6B76A0A48', desc.fingerprint) - self.assertTrue(CRYPTO_BLOB in desc.signature) + self.assertTrue(stem.descriptor.CRYPTO_BLOB in desc.signature)
def test_unrecognized_line(self): """ @@ -206,16 +212,14 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw Includes a line prior to the 'extra-info' entry. """
- desc_text = b'exit-streams-opened port=80\n' + RelayExtraInfoDescriptor.content() - self._expect_invalid_attr(desc_text) + expect_invalid_attr_for_text(self, b'exit-streams-opened port=80\n' + RelayExtraInfoDescriptor.content())
def test_trailing_line(self): """ Includes a line after the 'router-signature' entry. """
- desc_text = RelayExtraInfoDescriptor.content() + b'\nexit-streams-opened port=80' - self._expect_invalid_attr(desc_text) + expect_invalid_attr_for_text(self, RelayExtraInfoDescriptor.content() + b'\nexit-streams-opened port=80')
def test_extrainfo_line_missing_fields(self): """ @@ -232,8 +236,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({'extra-info': entry}) - desc = self._expect_invalid_attr(desc_text, 'nickname') + desc = expect_invalid_attr(self, {'extra-info': entry}, 'nickname') self.assertEqual(None, desc.nickname) self.assertEqual(None, desc.fingerprint)
@@ -259,11 +262,8 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({'geoip-db-digest': entry}) - self._expect_invalid_attr(desc_text, 'geoip_db_digest') - - desc_text = RelayExtraInfoDescriptor.content({'geoip6-db-digest': entry}) - self._expect_invalid_attr(desc_text, 'geoip6_db_digest') + expect_invalid_attr(self, {'geoip-db-digest': entry}, 'geoip_db_digest') + expect_invalid_attr(self, {'geoip6-db-digest': entry}, 'geoip6_db_digest')
def test_cell_circuits_per_decile(self): """ @@ -287,8 +287,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({'cell-circuits-per-decile': entry}) - self._expect_invalid_attr(desc_text, 'cell_circuits_per_decile') + expect_invalid_attr(self, {'cell-circuits-per-decile': entry}, 'cell_circuits_per_decile')
def test_dir_response_lines(self): """ @@ -315,8 +314,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({keyword: entry}) - desc = self._expect_invalid_attr(desc_text) + desc = expect_invalid_attr(self, {keyword: entry}) self.assertEqual(None, getattr(desc, attr)) self.assertEqual(None, getattr(desc, unknown_attr))
@@ -357,8 +355,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({keyword: entry}) - desc = self._expect_invalid_attr(desc_text) + desc = expect_invalid_attr(self, {keyword: entry}) self.assertEqual(None, getattr(desc, attr)) self.assertEqual(None, getattr(desc, unknown_attr))
@@ -388,8 +385,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({'conn-bi-direct': entry}) - desc = self._expect_invalid_attr(desc_text) + desc = expect_invalid_attr(self, {'conn-bi-direct': entry}) self.assertEqual(None, desc.conn_bi_direct_end) self.assertEqual(None, desc.conn_bi_direct_interval) self.assertEqual(None, desc.conn_bi_direct_below) @@ -425,8 +421,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({keyword: entry}) - self._expect_invalid_attr(desc_text, attr) + expect_invalid_attr(self, {keyword: entry}, attr)
def test_number_list_lines(self): """ @@ -455,8 +450,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry, expected in test_entries: - desc_text = RelayExtraInfoDescriptor.content({keyword: entry}) - self._expect_invalid_attr(desc_text, attr, expected) + expect_invalid_attr(self, {keyword: entry}, attr, expected)
def test_timestamp_lines(self): """ @@ -478,8 +472,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({keyword: entry}) - self._expect_invalid_attr(desc_text, attr) + expect_invalid_attr(self, {keyword: entry}, attr)
def test_timestamp_and_interval_lines(self): """ @@ -506,8 +499,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({'entry-stats-end': entry}) - desc = self._expect_invalid_attr(desc_text) + desc = expect_invalid_attr(self, {'entry-stats-end': entry}) self.assertEqual(None, desc.entry_stats_end) self.assertEqual(None, desc.entry_stats_interval)
@@ -544,8 +536,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({'write-history': entry}) - desc = self._expect_invalid_attr(desc_text) + desc = expect_invalid_attr(self, {'write-history': entry}) self.assertEqual(None, desc.write_history_end) self.assertEqual(None, desc.write_history_interval) self.assertEqual(None, desc.write_history_values) @@ -579,8 +570,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({keyword: entry}) - self._expect_invalid_attr(desc_text, attr) + expect_invalid_attr(self, {keyword: entry}, attr)
def test_hidden_service_stats_end(self): """ @@ -601,8 +591,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({'hidserv-stats-end': entry}) - self._expect_invalid_attr(desc_text, 'hs_stats_end') + expect_invalid_attr(self, {'hidserv-stats-end': entry}, 'hs_stats_end')
def test_hidden_service_stats(self): """ @@ -644,9 +633,8 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw self.assertEqual({'spiffy': 'true', 'snowmen': 'neat'}, getattr(desc, extra_attr))
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({keyword: entry}) - self._expect_invalid_attr(desc_text, stat_attr) - self._expect_invalid_attr(desc_text, extra_attr, {}) + expect_invalid_attr(self, {keyword: entry}, stat_attr) + expect_invalid_attr(self, {keyword: entry}, extra_attr, {})
def test_locale_mapping_lines(self): """ @@ -674,8 +662,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw )
for entry in test_entries: - desc_text = RelayExtraInfoDescriptor.content({keyword: entry}) - self._expect_invalid_attr(desc_text, attr) + expect_invalid_attr(self, {keyword: entry}, attr)
def test_minimal_bridge_descriptor(self): """ @@ -737,24 +724,3 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw desc = BridgeExtraInfoDescriptor.create({'transport': 'obfs3\ntransport obfs4'}) self.assertEqual({'obfs3': (None, None, None), 'obfs4': (None, None, None)}, desc.transport) self.assertEqual([], desc.get_unrecognized_lines()) - - def _expect_invalid_attr(self, desc_text, attr = None, expected_value = None): - """ - Asserts that construction will fail due to desc_text 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, RelayExtraInfoDescriptor, desc_text, True) - desc = RelayExtraInfoDescriptor(desc_text, validate = False) - - if attr: - # check that the invalid attribute matches the expected value when - # constructed without validation - - self.assertEqual(expected_value, getattr(desc, attr)) - else: - # check a default attribute - self.assertEqual('ninja', desc.nickname) - - return desc diff --git a/test/unit/descriptor/server_descriptor.py b/test/unit/descriptor/server_descriptor.py index f30fed6..0014049 100644 --- a/test/unit/descriptor/server_descriptor.py +++ b/test/unit/descriptor/server_descriptor.py @@ -3,6 +3,7 @@ Unit tests for stem.descriptor.server_descriptor. """
import datetime +import functools import io import pickle import tarfile @@ -20,7 +21,11 @@ from stem.util import str_type from stem.descriptor.certificate import CertType, ExtensionType from stem.descriptor.server_descriptor import RelayDescriptor, BridgeDescriptor
-from test.unit.descriptor import get_resource +from test.unit.descriptor import ( + get_resource, + base_expect_invalid_attr, + base_expect_invalid_attr_for_text, +)
try: # added in python 3.3 @@ -34,6 +39,9 @@ TARFILE_FINGERPRINTS = set([ str_type('1F43EE37A0670301AD9CB555D94AFEC2C89FDE86'), ])
+expect_invalid_attr = functools.partial(base_expect_invalid_attr, RelayDescriptor, 'nickname', 'caerSidi') +expect_invalid_attr_for_text = functools.partial(base_expect_invalid_attr_for_text, RelayDescriptor, 'nickname', 'caerSidi') +
class TestServerDescriptor(unittest.TestCase): def test_with_tarfile_path(self): @@ -455,7 +463,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4= """
desc_text = b'hibernate 1\n' + RelayDescriptor.content() - self._expect_invalid_attr_for_text(desc_text) + expect_invalid_attr_for_text(self, desc_text)
def test_trailing_line(self): """ @@ -463,56 +471,56 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4= """
desc_text = RelayDescriptor.content() + b'\nhibernate 1' - self._expect_invalid_attr_for_text(desc_text) + expect_invalid_attr_for_text(self, desc_text)
def test_nickname_missing(self): """ Constructs with a malformed router entry. """
- self._expect_invalid_attr({'router': ' 71.35.133.197 9001 0 0'}, 'nickname') + expect_invalid_attr(self, {'router': ' 71.35.133.197 9001 0 0'}, 'nickname')
def test_nickname_too_long(self): """ Constructs with a nickname that is an invalid length. """
- self._expect_invalid_attr({'router': 'saberrider2008ReallyLongNickname 71.35.133.197 9001 0 0'}, 'nickname') + expect_invalid_attr(self, {'router': 'saberrider2008ReallyLongNickname 71.35.133.197 9001 0 0'}, 'nickname')
def test_nickname_invalid_char(self): """ Constructs with an invalid relay nickname. """
- self._expect_invalid_attr({'router': '$aberrider2008 71.35.133.197 9001 0 0'}, 'nickname') + expect_invalid_attr(self, {'router': '$aberrider2008 71.35.133.197 9001 0 0'}, 'nickname')
def test_address_malformed(self): """ Constructs with an invalid ip address. """
- self._expect_invalid_attr({'router': 'caerSidi 371.35.133.197 9001 0 0'}, 'address') + expect_invalid_attr(self, {'router': 'caerSidi 371.35.133.197 9001 0 0'}, 'address')
def test_port_too_high(self): """ Constructs with an ORPort that is too large. """
- self._expect_invalid_attr({'router': 'caerSidi 71.35.133.197 900001 0 0'}, 'or_port') + expect_invalid_attr(self, {'router': 'caerSidi 71.35.133.197 900001 0 0'}, 'or_port')
def test_port_malformed(self): """ Constructs with an ORPort that isn't numeric. """
- self._expect_invalid_attr({'router': 'caerSidi 71.35.133.197 900a1 0 0'}, 'or_port') + expect_invalid_attr(self, {'router': 'caerSidi 71.35.133.197 900a1 0 0'}, 'or_port')
def test_port_newline(self): """ Constructs with a newline replacing the ORPort. """
- self._expect_invalid_attr({'router': 'caerSidi 71.35.133.197 \n 0 0'}, 'or_port') + expect_invalid_attr(self, {'router': 'caerSidi 71.35.133.197 \n 0 0'}, 'or_port')
def test_platform_empty(self): """ @@ -543,7 +551,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4= Constructs with a protocols line without circuit versions. """
- self._expect_invalid_attr({'opt': 'protocols Link 1 2'}, 'circuit_protocols') + expect_invalid_attr(self, {'opt': 'protocols Link 1 2'}, 'circuit_protocols')
@patch('stem.prereq.is_crypto_available', Mock(return_value = False)) def test_published_leap_year(self): @@ -552,7 +560,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4= invalid. """
- self._expect_invalid_attr({'published': '2011-02-29 04:03:19'}, 'published') + expect_invalid_attr(self, {'published': '2011-02-29 04:03:19'}, 'published')
desc = RelayDescriptor.create({'published': '2012-02-29 04:03:19'}) self.assertEqual(datetime.datetime(2012, 2, 29, 4, 3, 19), desc.published) @@ -562,7 +570,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4= Constructs with a published entry without a time component. """
- self._expect_invalid_attr({'published': '2012-01-01'}, 'published') + expect_invalid_attr(self, {'published': '2012-01-01'}, 'published')
def test_read_and_write_history(self): """ @@ -632,7 +640,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
desc_text = RelayDescriptor.content({'<replace>': ''}) desc_text = desc_text.replace(b'<replace>', b'contact foo\ncontact bar') - self._expect_invalid_attr_for_text(desc_text, 'contact', b'foo') + expect_invalid_attr_for_text(self, desc_text, 'contact', b'foo')
def test_missing_required_attr(self): """ @@ -661,7 +669,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4= """
fingerprint = '4F0C 867D F0EF 6816 0568 C826 838F 482C EA7C FE45' - self._expect_invalid_attr({'opt fingerprint': fingerprint}, 'fingerprint', fingerprint.replace(' ', '')) + expect_invalid_attr(self, {'opt fingerprint': fingerprint}, 'fingerprint', fingerprint.replace(' ', ''))
def test_ipv6_policy(self): """ @@ -829,28 +837,6 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4= desc = BridgeDescriptor(desc_text) self.assertEqual(expected_or_addresses, desc.or_addresses)
- def _expect_invalid_attr(self, desc_attrs, attr = None, expected_value = None): - self._expect_invalid_attr_for_text(RelayDescriptor.content(desc_attrs), attr, expected_value) - - def _expect_invalid_attr_for_text(self, desc_text, attr = None, expected_value = None): - """ - Asserts that construction will fail due to desc_text 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, RelayDescriptor, desc_text, True) - desc = RelayDescriptor(desc_text, validate = False) - - if attr: - # check that the invalid attribute matches the expected value when - # constructed without validation - - self.assertEqual(expected_value, getattr(desc, attr)) - else: - # check a default attribute - self.assertEqual('caerSidi', desc.nickname) - def test_pickleability(self): """ Checks that we can unpickle lazy loaded server descriptors.