[tor-commits] [sbws/maint-1.1] chg: relayprioritizer: Count priorities with timestamps

juga at torproject.org juga at torproject.org
Tue Apr 14 13:53:19 UTC 2020


commit c7c91370f5008aa4757340799e880e175d3b8830
Author: juga0 <juga at riseup.net>
Date:   Sat Mar 21 14:49:50 2020 +0000

    chg: relayprioritizer: Count priorities with timestamps
    
    in RelayPrioritizer:
    - Rename recent_priority_list_count to recent_priority_list when
      there is no counting
    - Rename recent_priority_relay_count to recent_priority_relay
      when there is no counting
    - Use the timestamps class to manage/count priority lists/relays
---
 sbws/lib/relayprioritizer.py            | 38 +++++++++++------
 sbws/lib/v3bwfile.py                    |  4 +-
 tests/conftest.py                       | 30 +++++++++++++
 tests/unit/conftest.py                  | 11 +++++
 tests/unit/lib/test_relayprioritizer.py | 76 +++++++++++++++++++++++++++++++++
 tests/unit/lib/test_v3bwfile.py         | 20 +++++++++
 6 files changed, 163 insertions(+), 16 deletions(-)

diff --git a/sbws/lib/relayprioritizer.py b/sbws/lib/relayprioritizer.py
index 4932ea8..3647a8b 100644
--- a/sbws/lib/relayprioritizer.py
+++ b/sbws/lib/relayprioritizer.py
@@ -6,7 +6,8 @@ import copy
 import time
 import logging
 
-from ..util import state
+from ..globals import MAX_RECENT_PRIORITY_RELAY_COUNT
+from ..util import state, timestamps
 
 log = logging.getLogger(__name__)
 
@@ -24,30 +25,39 @@ class RelayPrioritizer:
         self.fraction_to_return = conf.getfloat(
             'relayprioritizer', 'fraction_relays')
         self._state = state.State(conf.getpath('paths', 'state_fname'))
-        if self._state is not None:
-            # If it was not in previous state versions, initialize it to 0
-            if self._state.get('recent_priority_list_count', None) is None:
-                self._state['recent_priority_list_count'] = 0
-            if self._state.get('recent_priority_relay_count') is None:
-                self._state['recent_priority_relay_count'] = 0
-
-    def increment_priority_lists(self):
+        self._recent_priority_list = timestamps.DateTimeSeq(
+            [], 120, self._state, "recent_priority_list"
+        )
+        self._recent_priority_relay = timestamps.DateTimeIntSeq(
+            [],  MAX_RECENT_PRIORITY_RELAY_COUNT, self._state,
+            "recent_priority_relay"
+        )
+
+    def increment_recent_priority_list(self):
         """
         Increment the number of times that
         :meth:`~sbws.lib.relayprioritizer.RelayPrioritizer.best_priority`
         has been run.
         """
         # NOTE: blocking, writes to file!
-        self._state['recent_priority_list_count'] += 1
+        self._recent_priority_list.update()
 
-    def increment_priority_relays(self, relays_count):
+    @property
+    def recent_priority_list_count(self):
+        return len(self._recent_priority_list)
+
+    def increment_recent_priority_relay(self, relays_count):
         """
         Increment the number of relays that have been "prioritized" to be
         measured in a
         :meth:`~sbws.lib.relayprioritizer.RelayPrioritizer.best_priority`.
         """
         # NOTE: blocking, writes to file!
-        self._state['recent_priority_relay_count'] += relays_count
+        self._recent_priority_relay.update(number=relays_count)
+
+    @property
+    def recent_priority_relay_count(self):
+        return len(self._recent_priority_relay)
 
     def best_priority(self, prioritize_result_error=False,
                       return_fraction=True):
@@ -141,11 +151,11 @@ class RelayPrioritizer:
         upper_limit = cutoff if return_fraction else len(relays)
         # NOTE: these two are blocking, write to disk
         # Increment the number of times ``best_priority`` has been run.
-        self.increment_priority_lists()
+        self.increment_recent_priority_list()
         # Increment the number of relays that have been "prioritized".
         # Because in a small testing network the upper limit could be smaller
         # than the number of relays in the network, use the length of the list.
-        self.increment_priority_relays(len(relays[0:upper_limit]))
+        self.increment_recent_priority_relay(len(relays[0:upper_limit]))
         for relay in relays[0:upper_limit]:
             log.debug('Returning next relay %s with priority %f',
                       relay.nickname, relay.priority)
diff --git a/sbws/lib/v3bwfile.py b/sbws/lib/v3bwfile.py
index f81ef82..ee9fd17 100644
--- a/sbws/lib/v3bwfile.py
+++ b/sbws/lib/v3bwfile.py
@@ -481,7 +481,7 @@ class V3BWHeader(object):
         in the recent (by default 5) days from the state file.
         """
         state = State(state_fpath)
-        return state.get('recent_priority_list_count', None)
+        return state.count('recent_priority_list')
 
     @staticmethod
     def recent_priority_relay_count_from_file(state_fpath):
@@ -490,7 +490,7 @@ class V3BWHeader(object):
         in the recent (by default 5) days from the state file.
         """
         state = State(state_fpath)
-        return state.get('recent_priority_relay_count', None)
+        return state.count('recent_priority_relay')
 
     @staticmethod
     def latest_bandwidth_from_results(results):
diff --git a/tests/conftest.py b/tests/conftest.py
index d968cac..b2b54d1 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -5,6 +5,10 @@ from unittest import mock
 
 from stem import descriptor
 
+from sbws import settings
+from sbws.lib import relaylist
+from sbws.lib import relayprioritizer
+from sbws.lib import resultdump
 from sbws.util.parser import create_parser
 
 
@@ -87,3 +91,29 @@ def controller_5days_later(router_statuses_5days_later):
     controller = mock.Mock()
     controller.get_network_statuses.return_value = router_statuses_5days_later
     return controller
+
+
+# Because of the function scoped `args` in `tests.unit.conftest`, this has to
+# be function scoped too.
+ at pytest.fixture(scope='function')
+def relay_list(args, conf, controller):
+    """Returns a RelayList containing the Relays in the controller"""
+    return relaylist.RelayList(args, conf, controller)
+
+
+ at pytest.fixture(scope='function')
+def result_dump(args, conf):
+    """Returns a ResultDump without Results"""
+    # To stop the thread that would be waiting for new results
+    settings.set_end_event()
+    return resultdump.ResultDump(args, conf)
+
+
+ at pytest.fixture(scope="function")
+def relay_prioritizer(args, conf_results, relay_list, result_dump):
+    """
+    Returns a RelayPrioritizer with a RelayList and a ResultDump.
+    """
+    return relayprioritizer.RelayPrioritizer(
+        args, conf_results, relay_list, result_dump
+    )
diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py
index 295e777..bc812f0 100644
--- a/tests/unit/conftest.py
+++ b/tests/unit/conftest.py
@@ -187,6 +187,17 @@ def conf(sbwshome_empty, tmpdir):
     return conf
 
 
+ at pytest.fixture(scope='function')
+def conf_results(sbwshome_success_result_two_relays, conf):
+    """Minimal configuration having a datadir
+
+    So that `ResultDump` does not raise AssertionError.
+
+    """
+    conf['paths']['sbws_home'] = sbwshome_success_result_two_relays
+    return conf
+
+
 @pytest.fixture()
 def result():
     return RESULT
diff --git a/tests/unit/lib/test_relayprioritizer.py b/tests/unit/lib/test_relayprioritizer.py
new file mode 100644
index 0000000..e692343
--- /dev/null
+++ b/tests/unit/lib/test_relayprioritizer.py
@@ -0,0 +1,76 @@
+"""relayprioritizer.py unit tests."""
+from freezegun import freeze_time
+
+
+def test_increment_recent_priority_list(relay_prioritizer):
+    """Test that incrementing the priority lists do not go on forever.
+
+    And instead it only counts the number of priority lists in the last days.
+    """
+
+    state = relay_prioritizer._state
+    assert 0 == relay_prioritizer.recent_priority_list_count
+    assert not state.get("recent_priority_list", None)
+
+    # Pretend that a priority list is made.
+    with freeze_time("2020-02-29 10:00:00"):
+        relay_prioritizer.increment_recent_priority_list()
+    assert 1 == relay_prioritizer.recent_priority_list_count
+    assert 1 == len(state["recent_priority_list"])
+
+    # And a second priority list is made 4 days later.
+    with freeze_time("2020-03-04 10:00:00"):
+        relay_prioritizer.increment_recent_priority_list()
+    assert 2 == relay_prioritizer.recent_priority_list_count
+    assert 2 == len(state["recent_priority_list"])
+
+    # And a third priority list is made 5 days later.
+    with freeze_time("2020-03-05 10:00:00"):
+        relay_prioritizer.increment_recent_priority_list()
+    assert 3 == relay_prioritizer.recent_priority_list_count
+    assert 3 == len(state["recent_priority_list"])
+
+    # And a fourth priority list is made 6 days later. The first one is
+    # now removed and not counted.
+    with freeze_time("2020-03-06 10:00:00"):
+        relay_prioritizer.increment_recent_priority_list()
+    assert 3 == relay_prioritizer.recent_priority_list_count
+    assert 3 == len(state["recent_priority_list"])
+
+
+def test_increment_priority_relay(relay_prioritizer):
+    """Test that incrementing the number of relays in the priority lists
+    do not go on forever.
+
+    And instead it only counts number of relays in priority lists in the last
+    days.
+    """
+
+    state = relay_prioritizer._state
+    assert 0 == relay_prioritizer.recent_priority_relay_count
+    assert not state.get("recent_priority_relay", None)
+
+    # Pretend that a priority list is made.
+    with freeze_time("2020-02-29 10:00:00"):
+        relay_prioritizer.increment_recent_priority_relay(2)
+    assert 2 == relay_prioritizer.recent_priority_relay_count
+    assert 2 == state.count("recent_priority_relay")
+
+    # And a second priority list is made 4 days later.
+    with freeze_time("2020-03-04 10:00:00"):
+        relay_prioritizer.increment_recent_priority_relay(2)
+    assert 4 == relay_prioritizer.recent_priority_relay_count
+    assert 4 == state.count("recent_priority_relay")
+
+    # And a third priority list is made 5 days later.
+    with freeze_time("2020-03-05 10:00:00"):
+        relay_prioritizer.increment_recent_priority_relay(2)
+    assert 6 == relay_prioritizer.recent_priority_relay_count
+    assert 6 == state.count("recent_priority_relay")
+
+    # And a fourth priority list is made 6 days later. The first one is
+    # now removed and the relays are not counted.
+    with freeze_time("2020-03-06 10:00:00"):
+        relay_prioritizer.increment_recent_priority_relay(2)
+    assert 6 == relay_prioritizer.recent_priority_relay_count
+    assert 6 == state.count("recent_priority_relay")
diff --git a/tests/unit/lib/test_v3bwfile.py b/tests/unit/lib/test_v3bwfile.py
index 2ce34ff..7d26b8d 100644
--- a/tests/unit/lib/test_v3bwfile.py
+++ b/tests/unit/lib/test_v3bwfile.py
@@ -551,3 +551,23 @@ def test_recent_measurement_attempt_count(root_data_path, datadir):
     results = load_result_file(str(datadir.join("results.txt")))
     header = V3BWHeader.from_results(results, '', '', state_fpath)
     assert "15" == header.recent_measurement_attempt_count
+
+
+def test_recent_priority_list_count(root_data_path, datadir):
+    # This state has recent_priority_list
+    state_fpath = os.path.join(root_data_path, '.sbws/state.dat')
+    assert 1 == V3BWHeader.recent_priority_list_count_from_file(state_fpath)
+    # `results` does not matter here, using them to don't have an empty list.
+    results = load_result_file(str(datadir.join("results.txt")))
+    header = V3BWHeader.from_results(results, '', '', state_fpath)
+    assert "1" == header.recent_priority_list_count
+
+
+def test_recent_priority_relay_count(root_data_path, datadir):
+    # This state has recent_priority_relay_count
+    state_fpath = os.path.join(root_data_path, '.sbws/state.dat')
+    assert 15 == V3BWHeader.recent_priority_relay_count_from_file(state_fpath)
+    # `results` does not matter here, using them to don't have an empty list.
+    results = load_result_file(str(datadir.join("results.txt")))
+    header = V3BWHeader.from_results(results, '', '', state_fpath)
+    assert "15" == header.recent_priority_relay_count





More information about the tor-commits mailing list