[tor-commits] [stem/master] Parsing consensus-methods attribute

atagar at torproject.org atagar at torproject.org
Sat Oct 13 18:35:45 UTC 2012


commit 65e92e80711999591441abbdf23a21321e4d9271
Author: Damian Johnson <atagar at 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)
+
 





More information about the tor-commits mailing list