[tor-commits] [stem/master] Unit test for parsing a minimal key certificate

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


commit 5d1a11fa4f479cac4d4987d9841889ea251b2eba
Author: Damian Johnson <atagar at torproject.org>
Date:   Wed Sep 26 09:00:22 2012 -0700

    Unit test for parsing a minimal key certificate
    
    Test for minimal key certificate parsing, and related fixes for the
    KeyCertificate class. The main gotcha in this is that KeyCertificates don't
    need to have a prescribed order (unlike other network status document
    fields).
---
 run_tests.py                                       |    2 +
 stem/descriptor/networkstatus.py                   |   14 +---
 test/unit/descriptor/networkstatus/__init__.py     |    2 +-
 .../descriptor/networkstatus/key_certificate.py    |   79 ++++++++++++++++++++
 4 files changed, 85 insertions(+), 12 deletions(-)

diff --git a/run_tests.py b/run_tests.py
index af2d09f..54e74b2 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -21,6 +21,7 @@ import test.unit.descriptor.reader
 import test.unit.descriptor.server_descriptor
 import test.unit.descriptor.extrainfo_descriptor
 import test.unit.descriptor.networkstatus.entry
+import test.unit.descriptor.networkstatus.key_certificate
 import test.unit.descriptor.networkstatus.document
 import test.unit.response.control_line
 import test.unit.response.control_message
@@ -117,6 +118,7 @@ UNIT_TESTS = (
   test.unit.descriptor.server_descriptor.TestServerDescriptor,
   test.unit.descriptor.extrainfo_descriptor.TestExtraInfoDescriptor,
   test.unit.descriptor.networkstatus.entry.TestRouterStatusEntry,
+  test.unit.descriptor.networkstatus.key_certificate.TestKeyCertificate,
   test.unit.descriptor.networkstatus.document.TestNetworkStatusDocument,
   test.unit.exit_policy.rule.TestExitPolicyRule,
   test.unit.exit_policy.policy.TestExitPolicy,
diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py
index 46adbfe..01fb2f3 100644
--- a/stem/descriptor/networkstatus.py
+++ b/stem/descriptor/networkstatus.py
@@ -801,7 +801,7 @@ class KeyCertificate(stem.descriptor.Descriptor):
   **\*** mandatory attribute
   """
   
-  def __init__(self, raw_content, validate):
+  def __init__(self, raw_content, validate = True):
     super(KeyCertificate, self).__init__(raw_content)
     
     self.version = None
@@ -817,7 +817,7 @@ class KeyCertificate(stem.descriptor.Descriptor):
     
     self._unrecognized_lines = []
     
-    self._parse(raw_contents, validate)
+    self._parse(raw_content, validate)
   
   def _parse(self, content, validate):
     """
@@ -847,14 +847,6 @@ class KeyCertificate(stem.descriptor.Descriptor):
         entry_count = len(entries.get(keyword, []))
         if entry_count > 1:
           raise ValueError("Key certificates can only have a single '%s' line, got %i:\n%s" % (keyword, entry_count, content))
-      
-      # Check that our field's order matches the spec. This isn't explicitely
-      # stated in the spec, but the network status document requires a specific
-      # order so it stands to reason that the key certificate (which is in it)
-      # needs ot match a prescribed order too.
-      
-      fields = [attr[0] for attr in KEY_CERTIFICATE_PARAMS]
-      _check_for_misordered_fields(entries, fields)
     
     for keyword, values in entries.items():
       value, block_contents = values[0]
@@ -936,7 +928,7 @@ class KeyCertificate(stem.descriptor.Descriptor):
     :returns: a list of unrecognized lines
     """
     
-    return self.unrecognized_lines
+    return self._unrecognized_lines
 
 # TODO: microdescriptors have a slightly different format (including a
 # 'method') - should probably be a subclass
diff --git a/test/unit/descriptor/networkstatus/__init__.py b/test/unit/descriptor/networkstatus/__init__.py
index d8483e2..d8c9657 100644
--- a/test/unit/descriptor/networkstatus/__init__.py
+++ b/test/unit/descriptor/networkstatus/__init__.py
@@ -2,5 +2,5 @@
 Unit tests for stem.descriptor.networkstatus.
 """
 
-__all__ = ["entry", "document"]
+__all__ = ["entry", "key_certificate", "document"]
 
diff --git a/test/unit/descriptor/networkstatus/key_certificate.py b/test/unit/descriptor/networkstatus/key_certificate.py
new file mode 100644
index 0000000..2d779e7
--- /dev/null
+++ b/test/unit/descriptor/networkstatus/key_certificate.py
@@ -0,0 +1,79 @@
+"""
+Unit tests for the KeyCertificate of stem.descriptor.networkstatus.
+"""
+
+import datetime
+import unittest
+
+from stem.descriptor.networkstatus import KeyCertificate
+
+sig_block = """\
+-----BEGIN %s-----
+MIGJAoGBAJ5itcJRYNEM3Qf1OVWLRkwjqf84oXPc2ZusaJ5zOe7TVvBMra9GNyc0
+NM9y6zVkHCAePAjr4KbW/8P1olA6FUE2LV9bozaU1jFf6K8B2OELKs5FUEW+n+ic
+GM0x6MhngyXonWOcKt5Gj+mAu5lrno9tpNbPkz2Utr/Pi0nsDhWlAgMBAAE=
+-----END %s-----\
+"""
+
+RSA_SIG = sig_block % ("RSA PUBLIC KEY", "RSA PUBLIC KEY")
+KEY_SIG = sig_block % ("SIGNATURE", "SIGNATURE")
+
+KEY_CERTIFICATE_ATTR = (
+  ("dir-key-certificate-version", "3"),
+  ("fingerprint", "27B6B5996C426270A5C95488AA5BCEB6BCC86956"),
+  ("dir-key-published", "2011-11-28 21:51:04"),
+  ("dir-key-expires", "2012-11-28 21:51:04"),
+  ("dir-identity-key", "\n" + RSA_SIG),
+  ("dir-signing-key", "\n" + RSA_SIG),
+  ("dir-key-certification", "\n" + KEY_SIG),
+)
+
+def get_key_certificate(attr = None, exclude = None):
+  """
+  Constructs a minimal key certificate with the given attributes.
+  
+  :param dict attr: keyword/value mappings to be included in the entry
+  :param list exclude: mandatory keywords to exclude from the entry
+  
+  :returns: str with customized key certificate content
+  """
+  
+  descriptor_lines = []
+  if attr is None: attr = {}
+  if exclude is None: exclude = []
+  attr = dict(attr) # shallow copy since we're destructive
+  
+  for keyword, value in KEY_CERTIFICATE_ATTR:
+    if keyword in exclude: continue
+    elif keyword in attr:
+      value = attr[keyword]
+      del attr[keyword]
+    
+    descriptor_lines.append("%s %s" % (keyword, value))
+  
+  # dump in any unused attributes
+  for attr_keyword, attr_value in attr.items():
+    descriptor_lines.append("%s %s" % (attr_keyword, attr_value))
+  
+  return "\n".join(descriptor_lines)
+
+class TestKeyCertificate(unittest.TestCase):
+  def test_minimal(self):
+    """
+    Parses a minimal key certificate.
+    """
+    
+    certificate = KeyCertificate(get_key_certificate())
+    
+    self.assertEqual(3, certificate.version)
+    self.assertEqual(None, certificate.address)
+    self.assertEqual(None, certificate.dir_port)
+    self.assertEqual("27B6B5996C426270A5C95488AA5BCEB6BCC86956", certificate.fingerprint)
+    self.assertEqual(RSA_SIG, certificate.identity_key)
+    self.assertEqual(datetime.datetime(2011, 11, 28, 21, 51, 4), certificate.published)
+    self.assertEqual(datetime.datetime(2012, 11, 28, 21, 51, 4), certificate.expires)
+    self.assertEqual(RSA_SIG, certificate.signing_key)
+    self.assertEqual(None, certificate.crosscert)
+    self.assertEqual(KEY_SIG, certificate.certification)
+    self.assertEqual([], certificate.get_unrecognized_lines())
+





More information about the tor-commits mailing list