[tor-commits] [stem/master] Test fallback persistence

atagar at torproject.org atagar at torproject.org
Fri Jan 12 18:16:53 UTC 2018


commit b514fafccaa6d42d823f9b528d7335b85422c1cc
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Jan 11 09:55:22 2018 -0800

    Test fallback persistence
    
    Adding a unit test to test persistance and reloading fallbacks. As expected,
    presently doesn't have the new fields.
---
 cache_fallback_directories.py  | 18 +--------------
 stem/descriptor/remote.py      | 37 ++++++++++++++++++++++++++++--
 stem/util/conf.py              |  7 ++++++
 test/unit/descriptor/remote.py | 52 +++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 94 insertions(+), 20 deletions(-)

diff --git a/cache_fallback_directories.py b/cache_fallback_directories.py
index 0e61cf21..c5926c8c 100755
--- a/cache_fallback_directories.py
+++ b/cache_fallback_directories.py
@@ -10,7 +10,6 @@ import re
 import sys
 
 import stem.descriptor.remote
-import stem.util.conf
 import stem.util.system
 
 try:
@@ -49,19 +48,4 @@ if __name__ == '__main__':
 
   print('Differences detected...\n')
   print(stem.descriptor.remote._fallback_directory_differences(cached_fallback_directories, latest_fallback_directories))
-
-  conf = stem.util.conf.Config()
-  conf.set('tor_commit', fallback_dir_commit)
-  conf.set('stem_commit', stem_commit)
-
-  for directory in sorted(latest_fallback_directories.values(), key = lambda x: x.fingerprint):
-    fingerprint = directory.fingerprint
-    conf.set('%s.address' % fingerprint, directory.address)
-    conf.set('%s.or_port' % fingerprint, str(directory.or_port))
-    conf.set('%s.dir_port' % fingerprint, str(directory.dir_port))
-
-    if directory.orport_v6:
-      conf.set('%s.orport6_address' % fingerprint, str(directory.orport_v6[0]))
-      conf.set('%s.orport6_port' % fingerprint, str(directory.orport_v6[1]))
-
-  conf.save(stem.descriptor.remote.CACHE_PATH)
+  stem.descriptor.remote.FallbackDirectory._write(latest_fallback_directories, fallback_dir_commit, stem_commit)
diff --git a/stem/descriptor/remote.py b/stem/descriptor/remote.py
index 8f5e5cc3..453061e0 100644
--- a/stem/descriptor/remote.py
+++ b/stem/descriptor/remote.py
@@ -969,7 +969,7 @@ class FallbackDirectory(Directory):
     self.header = header if header else {}
 
   @staticmethod
-  def from_cache():
+  def from_cache(path = CACHE_PATH):
     """
     Provides fallback directory information cached with Stem. Unlike
     :func:`~stem.descriptor.remote.FallbackDirectory.from_remote` this doesn't
@@ -977,12 +977,17 @@ class FallbackDirectory(Directory):
     these fallback directories are only as up to date as the Stem release we're
     using.
 
+    .. versionchanged:: 1.7.0
+       Added the path argument.
+
+    :param str path: cache file to load from
+
     :returns: **dict** of **str** fingerprints to their
       :class:`~stem.descriptor.remote.FallbackDirectory`
     """
 
     conf = stem.util.conf.Config()
-    conf.load(CACHE_PATH)
+    conf.load(path)
 
     results = {}
 
@@ -1179,6 +1184,34 @@ class FallbackDirectory(Directory):
 
     return section_lines
 
+  @staticmethod
+  def _write(fallbacks, tor_commit, stem_commit, path = CACHE_PATH):
+    """
+    Persists fallback directories to a location in a way that can be read by
+    from_cache().
+
+    :param dict fallbacks: mapping of fingerprints to their fallback directory
+    :param str tor_commit: tor commit the fallbacks came from
+    :param str stem_commit: stem commit the fallbacks came from
+    :param str path: location fallbacks will be persisted to
+    """
+
+    conf = stem.util.conf.Config()
+    conf.set('tor_commit', tor_commit)
+    conf.set('stem_commit', stem_commit)
+
+    for directory in sorted(fallbacks.values(), key = lambda x: x.fingerprint):
+      fingerprint = directory.fingerprint
+      conf.set('%s.address' % fingerprint, directory.address)
+      conf.set('%s.or_port' % fingerprint, str(directory.or_port))
+      conf.set('%s.dir_port' % fingerprint, str(directory.dir_port))
+
+      if directory.orport_v6:
+        conf.set('%s.orport6_address' % fingerprint, str(directory.orport_v6[0]))
+        conf.set('%s.orport6_port' % fingerprint, str(directory.orport_v6[1]))
+
+    conf.save(path)
+
   def __hash__(self):
     return _hash_attr(self, 'address', 'or_port', 'dir_port', 'fingerprint', 'nickname', 'has_extrainfo', 'orport_v6', 'header', parent = Directory)
 
diff --git a/stem/util/conf.py b/stem/util/conf.py
index d4af467d..a902cae1 100644
--- a/stem/util/conf.py
+++ b/stem/util/conf.py
@@ -447,6 +447,9 @@ class Config(object):
     #
     # Information for what values fail to load and why are reported to
     # 'stem.util.log'.
+
+    .. versionchanged:: 1.7.0
+       Class can now be used as a dictionary.
   """
 
   def __init__(self):
@@ -768,3 +771,7 @@ class Config(object):
         message_id = 'stem.util.conf.missing_config_key_%s' % key
         log.log_once(message_id, log.TRACE, "config entry '%s' not found, defaulting to '%s'" % (key, default))
         return default
+
+  def __getitem__(self, key):
+    with self._contents_lock:
+      return self._contents[key]
diff --git a/test/unit/descriptor/remote.py b/test/unit/descriptor/remote.py
index cc0d51b1..8bfdffc1 100644
--- a/test/unit/descriptor/remote.py
+++ b/test/unit/descriptor/remote.py
@@ -4,10 +4,12 @@ Unit tests for stem.descriptor.remote.
 
 import io
 import socket
+import tempfile
 import unittest
 
-import stem.prereq
 import stem.descriptor.remote
+import stem.prereq
+import stem.util.conf
 
 try:
   # added in python 3.3
@@ -236,6 +238,54 @@ class TestDescriptorDownloader(unittest.TestCase):
 
     self.assertEqual(expected, fallback_directories)
 
+  def test_fallback_persistence(self):
+    header = {'type': 'fallback', 'version': '2.0.0', 'timestamp': '20170526090242'}
+
+    expected = {
+      '0756B7CD4DFC8182BE23143FAC0642F515182CEB': stem.descriptor.remote.FallbackDirectory(
+        address = '5.9.110.236',
+        or_port = 9001,
+        dir_port = 9030,
+        fingerprint = '0756B7CD4DFC8182BE23143FAC0642F515182CEB',
+        nickname = 'rueckgrat',
+        has_extrainfo = True,
+        orport_v6 = ('2a01:4f8:162:51e2::2', 9001),
+        header = header,
+      ),
+      '01A9258A46E97FF8B2CAC7910577862C14F2C524': stem.descriptor.remote.FallbackDirectory(
+        address = '193.171.202.146',
+        or_port = 9001,
+        dir_port = 9030,
+        fingerprint = '01A9258A46E97FF8B2CAC7910577862C14F2C524',
+        nickname = None,
+        has_extrainfo = False,
+        orport_v6 = None,
+        header = header,
+      ),
+    }
+
+    excepted_config = {
+      'tor_commit': ['abc'],
+      'stem_commit': ['def'],
+      '01A9258A46E97FF8B2CAC7910577862C14F2C524.address': ['193.171.202.146'],
+      '01A9258A46E97FF8B2CAC7910577862C14F2C524.or_port': ['9001'],
+      '01A9258A46E97FF8B2CAC7910577862C14F2C524.dir_port': ['9030'],
+      '0756B7CD4DFC8182BE23143FAC0642F515182CEB.address': ['5.9.110.236'],
+      '0756B7CD4DFC8182BE23143FAC0642F515182CEB.or_port': ['9001'],
+      '0756B7CD4DFC8182BE23143FAC0642F515182CEB.dir_port': ['9030'],
+      '0756B7CD4DFC8182BE23143FAC0642F515182CEB.orport6_address': ['2a01:4f8:162:51e2::2'],
+      '0756B7CD4DFC8182BE23143FAC0642F515182CEB.orport6_port': ['9001'],
+    }
+
+    with tempfile.NamedTemporaryFile(prefix = 'fallbacks.') as tmp:
+      stem.descriptor.remote.FallbackDirectory._write(expected, 'abc', 'def', tmp.name)
+
+      conf = stem.util.conf.Config()
+      conf.load(tmp.name)
+      self.assertEqual(excepted_config, dict(conf))
+
+      #self.assertEqual(expected, stem.descriptor.remote.FallbackDirectory.from_cache(tmp.name))
+
   @patch(URL_OPEN)
   def test_fallback_directories_from_remote_empty(self, urlopen_mock):
     urlopen_mock.return_value = io.BytesIO('')





More information about the tor-commits mailing list