[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Server descriptor test for metrics content
commit d72c21de710ba78e16b6d0fa29949fb43a2e5eb6
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sat Mar 24 18:15:27 2012 -0700
Server descriptor test for metrics content
Test for parsing a single server descriptor and checking its content. This
includes a few fixes and improvements for the ServerDescriptorV2 class, the
most intersting of which is that declaring instance variables prior to init
makes a single reference. Hence all server descriptors were using the same exit
policy. Oops. :)
---
run_tests.py | 2 +
stem/descriptor/server_descriptor.py | 111 +++++++++++++++++-----------
test/integ/descriptor/__init__.py | 2 +-
test/integ/descriptor/server_descriptor.py | 83 +++++++++++++++++++++
4 files changed, 155 insertions(+), 43 deletions(-)
diff --git a/run_tests.py b/run_tests.py
index e0574d3..3cb259d 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -31,6 +31,7 @@ import test.integ.control.base_controller
import test.integ.socket.control_message
import test.integ.socket.control_socket
import test.integ.descriptor.reader
+import test.integ.descriptor.server_descriptor
import test.integ.util.conf
import test.integ.util.system
import test.integ.version
@@ -98,6 +99,7 @@ INTEG_TESTS = (
test.integ.util.conf.TestConf,
test.integ.util.system.TestSystem,
test.integ.descriptor.reader.TestDescriptorReader,
+ test.integ.descriptor.server_descriptor.TestServerDescriptor,
test.integ.version.TestVersion,
test.integ.socket.control_socket.TestControlSocket,
test.integ.socket.control_message.TestControlMessage,
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 70db1fe..7715a96 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -192,45 +192,33 @@ class ServerDescriptorV2(stem.descriptor.Descriptor):
Attributes:
nickname (str) - relay's nickname (*)
+ fingerprint (str) - fourty hex digits that make up the relay's fingerprint
address (str) - IPv4 address of the relay (*)
or_port (int) - port used for relaying (*)
socks_port (int) - deprecated attribute, always zero (*)
dir_port (int) - deprecated port used for descriptor mirroring (*)
- average_bandwidth (int) - rate of traffic relay is willing to relay in bytes/s (*)
- burst_bandwidth (int) - rate of traffic relay is willing to burst to in bytes/s (*)
- observed_bandwidth (int) - estimated capacity of the relay based on usage in bytes/s (*)
platform (str) - operating system and tor version
tor_version (stem.version.Version) - version of tor
- exit_policy (stem.exit_policy.ExitPolicy) - relay's stated exit policy
+ operating_system (str) - relay's operating system
+ uptime (int) - relay's uptime when published in seconds
published (datetime.datetime) - time in GMT when the descriptor was generated (*)
- fingerprint (str) - fourty hex digits that make up the relay's fingerprint
+ contact (str) - relay's contact information
hibernating (bool) - flag to indicate if the relay was hibernating when published (*)
- uptime (int) - relay's uptime when published in seconds
+ exit_policy (stem.exit_policy.ExitPolicy) - relay's stated exit policy
+ family (list) - nicknames or fingerprints of relays it has a declared family with (*)
+ average_bandwidth (int) - rate of traffic relay is willing to relay in bytes/s (*)
+ burst_bandwidth (int) - rate of traffic relay is willing to burst to in bytes/s (*)
+ observed_bandwidth (int) - estimated capacity of the relay based on usage in bytes/s (*)
onion_key (str) - key used to encrypt EXTEND cells (*)
onion_key_type (str) - block type of the onion_key, probably "RSA PUBLIC KEY" (*)
signing_key (str) - relay's long-term identity key (*)
signing_key_type (str) - block type of the signing_key, probably "RSA PUBLIC KEY" (*)
- router_sig (str) - signature for this descriptor (*)
- router_sig_type (str) - block type of the router_sig, probably "SIGNATURE" (*)
- contact (str) - relay's contact information
- family (list) - nicknames or fingerprints of relays it has a declared family with (*)
+ signature (str) - signature for this descriptor (*)
+ signature_type (str) - block type of the signature, probably "SIGNATURE" (*)
(*) required fields, others are left as None if undefined
"""
- nickname = address = or_port = socks_port = dir_port = None
- average_bandwidth = burst_bandwidth = observed_bandwidth = None
- platform = tor_version = published = fingerprint = uptime = None
- onion_key = onion_key_type = signing_key = signing_key_type = None
- router_sig = router_sig_type = contact = None
- hibernating = False
- family = unrecognized_lines = []
-
- # TODO: Until we have a proper ExitPolicy class this is just a list of the
- # exit policy strings...
-
- exit_policy = []
-
def __init__(self, contents, validate = True, annotations = None):
"""
Version 2 server descriptor constructor, created from an individual relay's
@@ -253,14 +241,49 @@ class ServerDescriptorV2(stem.descriptor.Descriptor):
stem.descriptor.Descriptor.__init__(self, contents)
- self._annotation_lines = annotations
- self._annotation_dict = {}
+ self.nickname = None
+ self.fingerprint = None
+ self.address = None
+ self.or_port = None
+ self.socks_port = None
+ self.dir_port = None
+ self.platform = None
+ self.tor_version = None
+ self.operating_system = None
+ self.uptime = None
+ self.published = None
+ self.contact = None
+ self.hibernating = False
+ self.family = []
+ self.average_bandwidth = None
+ self.burst_bandwidth = None
+ self.observed_bandwidth = None
+ self.onion_key = None
+ self.onion_key_type = None
+ self.signing_key = None
+ self.signing_key_type = None
+ self.signature = None
+ self.signature_type = None
+
+ # TODO: Until we have a proper ExitPolicy class this is just a list of the
+ # exit policy strings...
- for line in annotations:
- if " " in line:
- key, value = line.split(" ", 1)
- self._annotation_dict[key] = value
- else: self._annotation_dict[line] = None
+ self.exit_policy = []
+
+ self._unrecognized_lines = []
+
+ if annotations:
+ self._annotation_lines = annotations
+ self._annotation_dict = {}
+
+ for line in annotations:
+ if " " in line:
+ key, value = line.split(" ", 1)
+ self._annotation_dict[key] = value
+ else: self._annotation_dict[line] = None
+ else:
+ self._annotation_lines = []
+ self._annotation_dict = {}
# A descriptor contains a series of 'keyword lines' which are simply a
# keyword followed by an optional value. Lines can also be followed by a
@@ -271,7 +294,6 @@ class ServerDescriptorV2(stem.descriptor.Descriptor):
# does not matter so breaking it into key / value pairs.
entries = {}
-
remaining_contents = contents.split("\n")
while remaining_contents:
line = remaining_contents.pop(0)
@@ -343,12 +365,14 @@ class ServerDescriptorV2(stem.descriptor.Descriptor):
raise ValueError("Router line's SocksPort should be zero: %s" % router_comp[3])
elif not stem.util.connection.is_valid_port(router_comp[4], allow_zero = True):
raise ValueError("Router line's DirPort is invalid: %s" % router_comp[4])
+ elif not (router_comp[2].isdigit() and router_comp[3].isdigit() and router_comp[4].isdigit()):
+ continue
self.nickname = router_comp[0]
self.address = router_comp[1]
- self.or_port = router_comp[2]
- self.socks_port = router_comp[3]
- self.dir_port = router_comp[4]
+ self.or_port = int(router_comp[2])
+ self.socks_port = int(router_comp[3])
+ self.dir_port = int(router_comp[4])
elif keyword == "bandwidth":
# "bandwidth" bandwidth-avg bandwidth-burst bandwidth-observed
bandwidth_comp = value.split()
@@ -379,13 +403,16 @@ class ServerDescriptorV2(stem.descriptor.Descriptor):
# version followed by the os like the following...
# platform Tor 0.2.2.35 (git-73ff13ab3cc9570d) on Linux x86_64
#
- # There's no guerentee that we'll be able to pick out the version.
+ # There's no guerentee that we'll be able to pick these out the
+ # version, but might as well try to save our caller the effot.
- platform_comp = self.platform.split()
+ platform_match = re.match("^Tor (\S*).* on (.*)$", self.platform)
- if platform_comp[0] == "Tor" and len(platform_comp) >= 2:
+ if platform_match:
+ version_str, self.operating_system = platform_match.groups()
+
try:
- self.tor_version = stem.version.Version(platform_comp[1])
+ self.tor_version = stem.version.Version(version_str)
except ValueError: pass
elif keyword == "published":
# "published" YYYY-MM-DD HH:MM:SS
@@ -439,17 +466,17 @@ class ServerDescriptorV2(stem.descriptor.Descriptor):
if validate and (not block_type or not block_contents):
raise ValueError("Router signature line must be followed by a signature block: %s" % line)
- self.router_sig_type = block_type
- self.router_sig = block_contents
+ self.signature_type = block_type
+ self.signature = block_contents
elif keyword == "contact":
self.contact = value
elif keyword == "family":
self.family = value.split(" ")
else:
- self.unrecognized_lines.append(line)
+ self._unrecognized_lines.append(line)
def get_unrecognized_lines(self):
- return list(unrecognized_lines)
+ return list(self._unrecognized_lines)
def get_annotations(self):
"""
diff --git a/test/integ/descriptor/__init__.py b/test/integ/descriptor/__init__.py
index e1095ca..b143c2a 100644
--- a/test/integ/descriptor/__init__.py
+++ b/test/integ/descriptor/__init__.py
@@ -2,5 +2,5 @@
Integration tests for stem.descriptor.* contents.
"""
-__all__ = ["reader"]
+__all__ = ["reader", "server_descriptor"]
diff --git a/test/integ/descriptor/server_descriptor.py b/test/integ/descriptor/server_descriptor.py
new file mode 100644
index 0000000..34b77a4
--- /dev/null
+++ b/test/integ/descriptor/server_descriptor.py
@@ -0,0 +1,83 @@
+"""
+Integration tests for stem.descriptor.server_descriptor.
+"""
+
+import os
+import datetime
+import unittest
+
+import stem.version
+import stem.descriptor.server_descriptor
+
+my_dir = os.path.dirname(__file__)
+DESCRIPTOR_TEST_DATA = os.path.join(my_dir, "data")
+
+class TestServerDescriptor(unittest.TestCase):
+ def test_metrics_descriptor(self):
+ """
+ Parses and checks our results against a server descriptor from metrics.
+ """
+
+ descriptor_path = os.path.join(DESCRIPTOR_TEST_DATA, "example_descriptor")
+
+ descriptor_file = open(descriptor_path)
+ descriptor_contents = descriptor_file.read()
+ descriptor_file.close()
+
+ expected_published = datetime.datetime(2012, 3, 1, 17, 15, 27)
+
+ expected_family = [
+ "$0CE3CFB1E9CC47B63EA8869813BF6FAB7D4540C1",
+ "$1FD187E8F69A9B74C9202DC16A25B9E7744AB9F6",
+ "$74FB5EFA6A46DE4060431D515DC9A790E6AD9A7C",
+ "$77001D8DA9BF445B0F81AA427A675F570D222E6A",
+ "$B6D83EC2D9E18B0A7A33428F8CFA9C536769E209",
+ "$D2F37F46182C23AB747787FD657E680B34EAF892",
+ "$E0BD57A11F00041A9789577C53A1B784473669E4",
+ "$E5E3E9A472EAF7BE9682B86E92305DB4C71048EF",
+ ]
+
+ expected_onion_key = """-----BEGIN RSA PUBLIC KEY-----
+MIGJAoGBAJv5IIWQ+WDWYUdyA/0L8qbIkEVH/cwryZWoIaPAzINfrw1WfNZGtBmg
+skFtXhOHHqTRN4GPPrZsAIUOQGzQtGb66IQgT4tO/pj+P6QmSCCdTfhvGfgTCsC+
+WPi4Fl2qryzTb3QO5r5x7T8OsG2IBUET1bLQzmtbC560SYR49IvVAgMBAAE=
+-----END RSA PUBLIC KEY-----"""
+
+ expected_signing_key = """-----BEGIN RSA PUBLIC KEY-----
+MIGJAoGBAKwvOXyztVKnuYvpTKt+nS3XIKeO8dVungi8qGoeS+6gkR6lDtGfBTjd
+uE9UIkdAl9zi8/1Ic2wsUNHE9jiS0VgeupITGZY8YOyMJJ/xtV1cqgiWhq1dUYaq
+51TOtUogtAPgXPh4J+V8HbFFIcCzIh3qCO/xXo+DSHhv7SSif1VpAgMBAAE=
+-----END RSA PUBLIC KEY-----"""
+
+ expected_signature = """-----BEGIN SIGNATURE-----
+dskLSPz8beUW7bzwDjR6EVNGpyoZde83Ejvau+5F2c6cGnlu91fiZN3suE88iE6e
+758b9ldq5eh5mapb8vuuV3uO+0Xsud7IEOqfxdkmk0GKnUX8ouru7DSIUzUL0zqq
+Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
+-----END SIGNATURE-----"""
+
+ desc = stem.descriptor.server_descriptor.ServerDescriptorV2(descriptor_contents)
+ self.assertEquals("caerSidi", desc.nickname)
+ self.assertEquals("A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB", desc.fingerprint)
+ self.assertEquals("71.35.133.197", desc.address)
+ self.assertEquals(9001, desc.or_port)
+ self.assertEquals(0, desc.socks_port)
+ self.assertEquals(0, desc.dir_port)
+ self.assertEquals("Tor 0.2.1.30 on Linux x86_64", desc.platform)
+ self.assertEquals(stem.version.Version("0.2.1.30"), desc.tor_version)
+ self.assertEquals("Linux x86_64", desc.operating_system)
+ self.assertEquals(588217, desc.uptime)
+ self.assertEquals(expected_published, desc.published)
+ self.assertEquals("www.atagar.com/contact", desc.contact)
+ self.assertEquals(False, desc.hibernating)
+ self.assertEquals(expected_family, desc.family)
+ self.assertEquals(153600, desc.average_bandwidth)
+ self.assertEquals(256000, desc.burst_bandwidth)
+ self.assertEquals(104590, desc.observed_bandwidth)
+ self.assertEquals(["reject *:*"], desc.exit_policy)
+ self.assertEquals(expected_onion_key, desc.onion_key)
+ self.assertEquals("RSA PUBLIC KEY", desc.onion_key_type)
+ self.assertEquals(expected_signing_key, desc.signing_key)
+ self.assertEquals("RSA PUBLIC KEY", desc.signing_key_type)
+ self.assertEquals(expected_signature, desc.signature)
+ self.assertEquals("SIGNATURE", desc.signature_type)
+
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits