commit 0cede13371c0796a5a819ef65466b9d2aaf0b806 Author: Damian Johnson atagar@torproject.org Date: Sun Jan 5 16:15:20 2014 -0800
Testing the ResourceTracker class
Unit tests for our daemon that tracks the resource usage of tor. --- arm/util/tracker.py | 20 ++--- test/util/tracker/resource_tracker.py | 142 +++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 10 deletions(-)
diff --git a/arm/util/tracker.py b/arm/util/tracker.py index 1a716d3..b0f99b2 100644 --- a/arm/util/tracker.py +++ b/arm/util/tracker.py @@ -31,7 +31,7 @@ Background tasks for gathering information about the tor process. :var float cpu_average: average cpu usage since we first started tracking the process :var float cpu_total: total cpu time the process has used since starting :var int memory_bytes: memory usage of the process in bytes - :var float memory_precent: percentage of our memory used by this process + :var float memory_percent: percentage of our memory used by this process :var float timestamp: unix timestamp for when this information was fetched """
@@ -70,7 +70,7 @@ def get_connection_tracker(): global CONNECTION_TRACKER
if CONNECTION_TRACKER is None: - CONNECTION_TRACKER = ConnectionTracker() + CONNECTION_TRACKER = ConnectionTracker(CONFIG['queries.connections.rate'])
return CONNECTION_TRACKER
@@ -83,7 +83,7 @@ def get_resource_tracker(): global RESOURCE_TRACKER
if RESOURCE_TRACKER is None: - RESOURCE_TRACKER = ResourceTracker() + RESOURCE_TRACKER = ResourceTracker(CONFIG['queries.resources.rate'])
return RESOURCE_TRACKER
@@ -147,9 +147,9 @@ def _resources_via_ps(pid): total_cpu_time = str_tools.parse_short_time_label(stats[0]) uptime = str_tools.parse_short_time_label(stats[1]) memory_bytes = int(stats[2]) * 1024 # ps size is in kb - memory_precent = float(stats[3]) / 100.0 + memory_percent = float(stats[3]) / 100.0
- return (total_cpu_time, uptime, memory_bytes, memory_precent) + return (total_cpu_time, uptime, memory_bytes, memory_percent) except ValueError: pass
@@ -320,8 +320,8 @@ class ConnectionTracker(Daemon): Periodically retrieves the connections established by tor. """
- def __init__(self): - super(ConnectionTracker, self).__init__(CONFIG['queries.connections.rate']) + def __init__(self, rate): + super(ConnectionTracker, self).__init__(rate)
self._connections = [] self._resolvers = connection.get_system_resolvers() @@ -437,8 +437,8 @@ class ResourceTracker(Daemon): Periodically retrieves the resource usage of tor. """
- def __init__(self): - super(ResourceTracker, self).__init__(CONFIG['queries.resources.rate']) + def __init__(self, rate): + super(ResourceTracker, self).__init__(rate)
self._resources = None self._use_proc = proc.is_available() # determines if we use proc or ps for lookups @@ -469,7 +469,7 @@ class ResourceTracker(Daemon): cpu_average = total_cpu_time / uptime, cpu_total = total_cpu_time, memory_bytes = memory_in_bytes, - memory_precent = memory_in_percent, + memory_percent = memory_in_percent, timestamp = time.time(), )
diff --git a/test/util/tracker/resource_tracker.py b/test/util/tracker/resource_tracker.py new file mode 100644 index 0000000..70cdf27 --- /dev/null +++ b/test/util/tracker/resource_tracker.py @@ -0,0 +1,142 @@ +import time +import unittest + +from arm.util.tracker import ResourceTracker, _resources_via_ps, _resources_via_proc + +from mock import Mock, patch + +PS_OUTPUT = """\ + TIME ELAPSED RSS %MEM +00:00:02 00:18 18848 0.4 +""" + + +class TestResourceTracker(unittest.TestCase): + @patch('arm.util.tracker.tor_controller') + @patch('arm.util.tracker._resources_via_proc') + @patch('arm.util.tracker.system', Mock(return_value = Mock())) + @patch('arm.util.tracker.proc.is_available', Mock(return_value = True)) + def test_fetching_samplings(self, resources_via_proc_mock, tor_controller_mock): + tor_controller_mock().get_pid.return_value = 12345 + resources_via_proc_mock.return_value = (105.3, 2.4, 8072, 0.3) + + with ResourceTracker(0.04) as daemon: + time.sleep(0.01) + + resources = daemon.get_resource_usage() + + self.assertEqual(1, daemon.run_counter()) + self.assertEqual(0.0, resources.cpu_sample) + self.assertEqual(43.875, resources.cpu_average) + self.assertEqual(105.3, resources.cpu_total) + self.assertEqual(8072, resources.memory_bytes) + self.assertEqual(0.3, resources.memory_percent) + self.assertTrue((time.time() - resources.timestamp) < 0.5) + + resources_via_proc_mock.return_value = (800.3, 3.2, 6020, 0.26) + time.sleep(0.05) + resources = daemon.get_resource_usage() + + self.assertEqual(2, daemon.run_counter()) + self.assertEqual(6.600189933523267, resources.cpu_sample) + self.assertEqual(250.09374999999997, resources.cpu_average) + self.assertEqual(800.3, resources.cpu_total) + self.assertEqual(6020, resources.memory_bytes) + self.assertEqual(0.26, resources.memory_percent) + self.assertTrue((time.time() - resources.timestamp) < 0.5) + + resources_via_proc_mock.assert_called_with(12345) + + @patch('arm.util.tracker.tor_controller') + @patch('arm.util.tracker.proc.is_available') + @patch('arm.util.tracker._resources_via_ps', Mock(return_value = (105.3, 2.4, 8072, 0.3))) + @patch('arm.util.tracker._resources_via_proc', Mock(return_value = (340.3, 3.2, 6020, 0.26))) + @patch('arm.util.tracker.system', Mock(return_value = Mock())) + def test_picking_proc_or_ps(self, is_proc_available_mock, tor_controller_mock): + tor_controller_mock().get_pid.return_value = 12345 + + is_proc_available_mock.return_value = True + + with ResourceTracker(0.04) as daemon: + time.sleep(0.01) + + resources = daemon.get_resource_usage() + + self.assertEqual(1, daemon.run_counter()) + self.assertEqual(0.0, resources.cpu_sample) + self.assertEqual(106.34375, resources.cpu_average) + self.assertEqual(340.3, resources.cpu_total) + self.assertEqual(6020, resources.memory_bytes) + self.assertEqual(0.26, resources.memory_percent) + self.assertTrue((time.time() - resources.timestamp) < 0.5) + + is_proc_available_mock.return_value = False + + with ResourceTracker(0.04) as daemon: + time.sleep(0.01) + + resources = daemon.get_resource_usage() + + self.assertEqual(1, daemon.run_counter()) + self.assertEqual(0.0, resources.cpu_sample) + self.assertEqual(43.875, resources.cpu_average) + self.assertEqual(105.3, resources.cpu_total) + self.assertEqual(8072, resources.memory_bytes) + self.assertEqual(0.3, resources.memory_percent) + self.assertTrue((time.time() - resources.timestamp) < 0.5) + + @patch('arm.util.tracker.tor_controller') + @patch('arm.util.tracker._resources_via_ps', Mock(return_value = (105.3, 2.4, 8072, 0.3))) + @patch('arm.util.tracker._resources_via_proc', Mock(side_effect = IOError())) + @patch('arm.util.tracker.system', Mock(return_value = Mock())) + @patch('arm.util.tracker.proc.is_available', Mock(return_value = True)) + def test_failing_over_to_ps(self, tor_controller_mock): + tor_controller_mock().get_pid.return_value = 12345 + + with ResourceTracker(0.01) as daemon: + time.sleep(0.03) + + self.assertEqual(True, daemon._use_proc) + resources = daemon.get_resource_usage() + + self.assertEqual(0, daemon.run_counter()) + self.assertEqual(0.0, resources.cpu_sample) + self.assertEqual(0.0, resources.cpu_average) + self.assertEqual(0, resources.cpu_total) + self.assertEqual(0, resources.memory_bytes) + self.assertEqual(0.0, resources.memory_percent) + self.assertEqual(0.0, resources.timestamp) + + time.sleep(0.05) + self.assertEqual(False, daemon._use_proc) + + resources = daemon.get_resource_usage() + + self.assertEqual(1, daemon.run_counter()) + self.assertEqual(0.0, resources.cpu_sample) + self.assertEqual(43.875, resources.cpu_average) + self.assertEqual(105.3, resources.cpu_total) + self.assertEqual(8072, resources.memory_bytes) + self.assertEqual(0.3, resources.memory_percent) + self.assertTrue((time.time() - resources.timestamp) < 0.5) + + @patch('arm.util.tracker.system.call', Mock(return_value = PS_OUTPUT.split('\n'))) + def test_resources_via_ps(self): + total_cpu_time, uptime, memory_in_bytes, memory_in_percent = _resources_via_ps(12345) + + self.assertEqual(2.0, total_cpu_time) + self.assertEqual(18, uptime) + self.assertEqual(19300352, memory_in_bytes) + self.assertEqual(0.004, memory_in_percent) + + @patch('time.time', Mock(return_value = 1388967218.973117)) + @patch('arm.util.tracker.proc.get_stats', Mock(return_value = (1.5, 0.5, 1388967200.9))) + @patch('arm.util.tracker.proc.get_memory_usage', Mock(return_value = (19300352, 6432))) + @patch('arm.util.tracker.proc.get_physical_memory', Mock(return_value = 4825088000)) + def test_resources_via_proc(self): + total_cpu_time, uptime, memory_in_bytes, memory_in_percent = _resources_via_proc(12345) + + self.assertEqual(2.0, total_cpu_time) + self.assertEqual(18, int(uptime)) + self.assertEqual(19300352, memory_in_bytes) + self.assertEqual(0.004, memory_in_percent)
tor-commits@lists.torproject.org