[tor-commits] [stem/master] Unit test downloading descriptors from orport

atagar at torproject.org atagar at torproject.org
Tue Apr 24 19:41:39 UTC 2018


commit 04186deb315d7b2d3ec1074757604d5f98656116
Author: Damian Johnson <atagar at torproject.org>
Date:   Mon Apr 23 19:37:57 2018 -0700

    Unit test downloading descriptors from orport
---
 test/unit/descriptor/remote.py | 88 +++++++++++++++++++++++++++++++-----------
 1 file changed, 65 insertions(+), 23 deletions(-)

diff --git a/test/unit/descriptor/remote.py b/test/unit/descriptor/remote.py
index b2cfa7c1..7d92c695 100644
--- a/test/unit/descriptor/remote.py
+++ b/test/unit/descriptor/remote.py
@@ -29,9 +29,9 @@ except ImportError:
 
 try:
   # added in python 3.3
-  from unittest.mock import patch, Mock
+  from unittest.mock import patch, Mock, MagicMock
 except ImportError:
-  from mock import patch, Mock
+  from mock import patch, Mock, MagicMock
 
 # The urlopen() method is in a different location depending on if we're using
 # python 2.x or 3.x. The 2to3 converter accounts for this in imports, but not
@@ -126,10 +126,20 @@ HEADER = '\r\n'.join([
   'Content-Encoding: %s',
 ])
 
+ORPORT_DESCRIPTOR = 'HTTP/1.0 200 OK\n' + HEADER + '\n\n' + TEST_DESCRIPTOR
 
-def _urlopen_mock(data, encoding = 'identity'):
-  urlopen_mock = Mock()
-  urlopen_mock().read.return_value = data
+
+def _orport_mock(data):
+  connect_mock = MagicMock()
+  relay_mock = connect_mock().__enter__()
+  circ_mock = relay_mock.create_circuit().__enter__()
+  circ_mock.send().data = data
+  return connect_mock
+
+
+def _dirport_mock(data, encoding = 'identity'):
+  dirport_mock = Mock()
+  dirport_mock().read.return_value = data
 
   if stem.prereq.is_python_3():
     headers = HTTPMessage()
@@ -138,11 +148,11 @@ def _urlopen_mock(data, encoding = 'identity'):
       key, value = line.split(': ', 1)
       headers.add_header(key, encoding if key == 'Content-Encoding' else value)
 
-    urlopen_mock().headers = headers
+    dirport_mock().headers = headers
   else:
-    urlopen_mock().headers = HTTPMessage(io.BytesIO(HEADER % encoding))
+    dirport_mock().headers = HTTPMessage(io.BytesIO(HEADER % encoding))
 
-  return urlopen_mock
+  return dirport_mock
 
 
 class TestDescriptorDownloader(unittest.TestCase):
@@ -150,6 +160,38 @@ class TestDescriptorDownloader(unittest.TestCase):
     # prevent our mocks from impacting other tests
     stem.descriptor.remote.SINGLETON_DOWNLOADER = None
 
+  @patch('stem.client.Relay.connect', _orport_mock(ORPORT_DESCRIPTOR))
+  def test_using_orport(self):
+    """
+    Download a descriptor through the ORPort.
+    """
+
+    reply = stem.descriptor.remote.their_server_descriptor(
+      endpoints = [stem.ORPort('12.34.56.78', 1100)],
+      fall_back_to_authority = False,
+      validate = True,
+    )
+
+    self.assertEqual(1, len(list(reply)))
+    self.assertEqual('moria1', list(reply)[0].nickname)
+    self.assertEqual(5, len(reply.reply_headers))
+
+  @patch(URL_OPEN, _dirport_mock(TEST_DESCRIPTOR))
+  def test_using_dirport(self):
+    """
+    Download a descriptor through the DirPort.
+    """
+
+    reply = stem.descriptor.remote.their_server_descriptor(
+      endpoints = [stem.DirPort('12.34.56.78', 1100)],
+      fall_back_to_authority = False,
+      validate = True,
+    )
+
+    self.assertEqual(1, len(list(reply)))
+    self.assertEqual('moria1', list(reply)[0].nickname)
+    self.assertEqual(5, len(reply.reply_headers))
+
   def test_gzip_url_override(self):
     query = stem.descriptor.remote.Query(TEST_RESOURCE, start = False)
     self.assertEqual([Compression.PLAINTEXT], query.compression)
@@ -177,7 +219,7 @@ class TestDescriptorDownloader(unittest.TestCase):
       query = stem.descriptor.remote.Query(TEST_RESOURCE, compression = Compression.LZMA, start = False)
       self.assertEqual([Compression.PLAINTEXT], query.compression)
 
-  @patch(URL_OPEN, _urlopen_mock(read_resource('compressed_identity'), encoding = 'identity'))
+  @patch(URL_OPEN, _dirport_mock(read_resource('compressed_identity'), encoding = 'identity'))
   def test_compression_plaintext(self):
     """
     Download a plaintext descriptor.
@@ -192,7 +234,7 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertEqual(1, len(descriptors))
     self.assertEqual('moria1', descriptors[0].nickname)
 
-  @patch(URL_OPEN, _urlopen_mock(read_resource('compressed_gzip'), encoding = 'gzip'))
+  @patch(URL_OPEN, _dirport_mock(read_resource('compressed_gzip'), encoding = 'gzip'))
   def test_compression_gzip(self):
     """
     Download a gip compressed descriptor.
@@ -207,7 +249,7 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertEqual(1, len(descriptors))
     self.assertEqual('moria1', descriptors[0].nickname)
 
-  @patch(URL_OPEN, _urlopen_mock(read_resource('compressed_zstd'), encoding = 'x-zstd'))
+  @patch(URL_OPEN, _dirport_mock(read_resource('compressed_zstd'), encoding = 'x-zstd'))
   def test_compression_zstd(self):
     """
     Download a zstd compressed descriptor.
@@ -226,7 +268,7 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertEqual(1, len(descriptors))
     self.assertEqual('moria1', descriptors[0].nickname)
 
-  @patch(URL_OPEN, _urlopen_mock(read_resource('compressed_lzma'), encoding = 'x-tor-lzma'))
+  @patch(URL_OPEN, _dirport_mock(read_resource('compressed_lzma'), encoding = 'x-tor-lzma'))
   def test_compression_lzma(self):
     """
     Download a lzma compressed descriptor.
@@ -245,7 +287,7 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertEqual(1, len(descriptors))
     self.assertEqual('moria1', descriptors[0].nickname)
 
-  @patch(URL_OPEN, _urlopen_mock(TEST_DESCRIPTOR))
+  @patch(URL_OPEN, _dirport_mock(TEST_DESCRIPTOR))
   def test_reply_headers(self):
     query = stem.descriptor.remote.get_server_descriptors('9695DFC35FFEB861329B9F1AB04C46397020CE31', start = False)
     self.assertEqual(None, query.reply_headers)  # initially we don't have a reply
@@ -268,7 +310,7 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertEqual(1, len(descriptors))
     self.assertEqual('moria1', descriptors[0].nickname)
 
-  @patch(URL_OPEN, _urlopen_mock(TEST_DESCRIPTOR))
+  @patch(URL_OPEN, _dirport_mock(TEST_DESCRIPTOR))
   def test_query_download(self):
     """
     Check Query functionality when we successfully download a descriptor.
@@ -293,7 +335,7 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertEqual('9695DFC35FFEB861329B9F1AB04C46397020CE31', desc.fingerprint)
     self.assertEqual(TEST_DESCRIPTOR.strip(), desc.get_bytes())
 
-  @patch(URL_OPEN, _urlopen_mock(b'some malformed stuff'))
+  @patch(URL_OPEN, _dirport_mock(b'some malformed stuff'))
   def test_query_with_malformed_content(self):
     """
     Query with malformed descriptor content.
@@ -321,12 +363,12 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertRaises(ValueError, query.run)
 
   @patch(URL_OPEN)
-  def test_query_with_timeout(self, urlopen_mock):
+  def test_query_with_timeout(self, dirport_mock):
     def urlopen_call(*args, **kwargs):
       time.sleep(0.06)
       raise socket.timeout('connection timed out')
 
-    urlopen_mock.side_effect = urlopen_call
+    dirport_mock.side_effect = urlopen_call
 
     query = stem.descriptor.remote.Query(
       TEST_RESOURCE,
@@ -341,7 +383,7 @@ class TestDescriptorDownloader(unittest.TestCase):
     # Check that we don't make a third.
 
     self.assertRaises(socket.timeout, query.run)
-    self.assertEqual(2, urlopen_mock.call_count)
+    self.assertEqual(2, dirport_mock.call_count)
 
   def test_query_with_invalid_endpoints(self):
     invalid_endpoints = {
@@ -355,7 +397,7 @@ class TestDescriptorDownloader(unittest.TestCase):
       expected_error = re.escape('Endpoints must be an stem.ORPort, stem.DirPort, or two value tuple. ' + error_suffix)
       self.assertRaisesRegexp(ValueError, expected_error, stem.descriptor.remote.Query, TEST_RESOURCE, 'server-descriptor 1.0', endpoints = endpoints)
 
-  @patch(URL_OPEN, _urlopen_mock(TEST_DESCRIPTOR))
+  @patch(URL_OPEN, _dirport_mock(TEST_DESCRIPTOR))
   def test_can_iterate_multiple_times(self):
     query = stem.descriptor.remote.Query(
       TEST_RESOURCE,
@@ -381,7 +423,7 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertTrue(len(fallback_directories) > 10)
     self.assertEqual('5.39.92.199', fallback_directories['0BEA4A88D069753218EAAAD6D22EA87B9A1319D6'].address)
 
-  @patch(URL_OPEN, _urlopen_mock(FALLBACK_DIR_CONTENT))
+  @patch(URL_OPEN, _dirport_mock(FALLBACK_DIR_CONTENT))
   def test_fallback_directories_from_remote(self):
     fallback_directories = stem.descriptor.remote.FallbackDirectory.from_remote()
     header = OrderedDict((('type', 'fallback'), ('version', '2.0.0'), ('timestamp', '20170526090242')))
@@ -465,15 +507,15 @@ class TestDescriptorDownloader(unittest.TestCase):
 
       self.assertEqual(expected, stem.descriptor.remote.FallbackDirectory.from_cache(tmp.name))
 
-  @patch(URL_OPEN, _urlopen_mock(b''))
+  @patch(URL_OPEN, _dirport_mock(b''))
   def test_fallback_directories_from_remote_empty(self):
     self.assertRaisesRegexp(IOError, 'did not have any content', stem.descriptor.remote.FallbackDirectory.from_remote)
 
-  @patch(URL_OPEN, _urlopen_mock(b'\n'.join(FALLBACK_DIR_CONTENT.splitlines()[1:])))
+  @patch(URL_OPEN, _dirport_mock(b'\n'.join(FALLBACK_DIR_CONTENT.splitlines()[1:])))
   def test_fallback_directories_from_remote_no_header(self):
     self.assertRaisesRegexp(IOError, 'does not have a type field indicating it is fallback directory metadata', stem.descriptor.remote.FallbackDirectory.from_remote)
 
-  @patch(URL_OPEN, _urlopen_mock(FALLBACK_DIR_CONTENT.replace(b'version=2.0.0', b'version')))
+  @patch(URL_OPEN, _dirport_mock(FALLBACK_DIR_CONTENT.replace(b'version=2.0.0', b'version')))
   def test_fallback_directories_from_remote_malformed_header(self):
     self.assertRaisesRegexp(IOError, 'Malformed fallback directory header line: /\* version \*/', stem.descriptor.remote.FallbackDirectory.from_remote)
 





More information about the tor-commits mailing list