commit 65e92e80711999591441abbdf23a21321e4d9271 Author: Damian Johnson atagar@torproject.org Date: Sat Sep 8 18:18:38 2012 -0700
Parsing consensus-methods attribute
Only noteworthy bit is that the spec says 'Method "1" MUST be included.' so checking for that. --- stem/descriptor/networkstatus.py | 19 +++++++++++------ test/unit/descriptor/networkstatus/document.py | 25 ++++++++++++++++++++++- 2 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py index f4c3b40..7e7907f 100644 --- a/stem/descriptor/networkstatus.py +++ b/stem/descriptor/networkstatus.py @@ -328,6 +328,17 @@ class NetworkStatusDocument(stem.descriptor.Descriptor): self.is_consensus, self.is_vote = False, True elif validate: raise ValueError("A network status document's vote-status line can only be 'consensus' or 'vote', got '%s' instead" % value) + elif keyword == 'consensus-methods': + # "consensus-methods" IntegerList + + for entry in value.split(" "): + if entry.isdigit(): + self.consensus_methods.append(int(entry)) + elif validate: + raise ValueError("A network status document's consensus-methods must be a list of integer values, but was '%s'" % value) + + if validate and not (1 in self.consensus_methods): + raise ValueError("Network status votes must include consensus-method version 1")
# doing this validation afterward so we know our 'is_consensus' and # 'is_vote' attributes @@ -344,17 +355,11 @@ class NetworkStatusDocument(stem.descriptor.Descriptor): # ignore things the parse() method handles _read_keyword_line("network-status-version", content, False, True) _read_keyword_line("vote-status", content, False, True) + _read_keyword_line("consensus-methods", content, False, True)
vote = self.is_vote
if vote: - read_keyword_line("consensus-methods", True) - - if self.consensus_methods: - self.consensus_methods = [int(method) for method in self.consensus_methods.split(" ")] - else: - self.consensus_methods = [] - line = _read_keyword_line("published", content, validate, True)
if line: diff --git a/test/unit/descriptor/networkstatus/document.py b/test/unit/descriptor/networkstatus/document.py index 9b24a00..9301cce 100644 --- a/test/unit/descriptor/networkstatus/document.py +++ b/test/unit/descriptor/networkstatus/document.py @@ -10,7 +10,7 @@ from stem.descriptor.networkstatus import HEADER_STATUS_DOCUMENT_FIELDS, FOOTER_ NETWORK_STATUS_DOCUMENT_ATTR = { "network-status-version": "3", "vote-status": "consensus", - "consensus-methods": "9", + "consensus-methods": "1 9", "consensus-method": "9", "published": "2012-09-02 22:00:00", "valid-after": "2012-09-02 22:00:00", @@ -138,7 +138,7 @@ class TestNetworkStatusDocument(unittest.TestCase): self.assertEqual(False, document.is_consensus) self.assertEqual(True, document.is_vote) self.assertEqual(None, document.consensus_method) - self.assertEqual([9], document.consensus_methods) + self.assertEqual([1, 9], document.consensus_methods) self.assertEqual(datetime.datetime(2012, 9, 2, 22, 0, 0), document.published) self.assertEqual(datetime.datetime(2012, 9, 2, 22, 0, 0), document.valid_after) self.assertEqual(datetime.datetime(2012, 9, 2, 22, 0, 0), document.fresh_until) @@ -245,4 +245,25 @@ class TestNetworkStatusDocument(unittest.TestCase): document = NetworkStatusDocument(content, False) self.assertEquals(True, document.is_consensus) self.assertEquals(False, document.is_vote) + + def test_invalid_consensus_methods(self): + """ + Parses an invalid consensus-methods field. + """ + + test_values = ( + ("", []), + (" ", []), + ("1 2 3 a 5", [1, 2, 3, 5]), + ("1 2 3 4.0 5", [1, 2, 3, 5]), + ("2 3 4", [2, 3, 4]), # spec says version one must be included + ) + + for test_value, expected_consensus_methods in test_values: + content = get_network_status_document({"vote-status": "vote", "consensus-methods": test_value}) + self.assertRaises(ValueError, NetworkStatusDocument, content) + + document = NetworkStatusDocument(content, False) + self.assertEquals(expected_consensus_methods, document.consensus_methods) +
tor-commits@lists.torproject.org