commit 197ab0e2eca9a7cb27880158077d16c9fe442912 Author: Damian Johnson atagar@torproject.org Date: Sat Jul 9 20:33:55 2016 -0700
Test _draw_details() --- nyx/panel/connection.py | 126 +++++++++++++++++++++++---------------------- test/panel/connection.py | 131 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 194 insertions(+), 63 deletions(-)
diff --git a/nyx/panel/connection.py b/nyx/panel/connection.py index 87930a6..b5a3297 100644 --- a/nyx/panel/connection.py +++ b/nyx/panel/connection.py @@ -421,7 +421,12 @@ class ConnectionPanel(nyx.panel.DaemonPanel): _draw_title(subwindow, entries, self._show_details)
if is_showing_details: - self._draw_details(subwindow, selected, subwindow.width, is_scrollbar_visible) + _draw_details(subwindow, selected) + + # draw a 'T' pipe if connecting with the scrollbar + + if is_scrollbar_visible: + subwindow._addch(1, DETAILS_HEIGHT + 1, curses.ACS_TTEE)
if is_scrollbar_visible: subwindow.scrollbar(1 + details_offset, scroll, len(lines)) @@ -433,67 +438,6 @@ class ConnectionPanel(nyx.panel.DaemonPanel): if y >= subwindow.height: break
- def _draw_details(self, subwindow, selected, width, is_scrollbar_visible): - """ - Shows detailed information about the selected connection. - """ - - attr = (CONFIG['attr.connection.category_color'].get(selected.entry.get_type(), WHITE), BOLD) - - if selected.line_type == LineType.CIRCUIT_HEADER and selected.circuit.status != 'BUILT': - subwindow.addstr(2, 1, 'Building Circuit...', *attr) - else: - address = '<scrubbed>' if selected.entry.is_private() else selected.connection.remote_address - subwindow.addstr(2, 1, 'address: %s:%s' % (address, selected.connection.remote_port), *attr) - subwindow.addstr(2, 2, 'locale: %s' % ('??' if selected.entry.is_private() else (selected.locale if selected.locale else '??')), *attr) - - matches = nyx.tracker.get_consensus_tracker().get_relay_fingerprints(selected.connection.remote_address) - - if not matches: - subwindow.addstr(2, 3, 'No consensus data found', *attr) - elif len(matches) == 1 or selected.connection.remote_port in matches: - controller = tor_controller() - fingerprint = matches.values()[0] if len(matches) == 1 else matches[selected.connection.remote_port] - router_status_entry = controller.get_network_status(fingerprint, None) - - subwindow.addstr(15, 2, 'fingerprint: %s' % fingerprint, *attr) - - if router_status_entry: - dir_port_label = 'dirport: %s' % router_status_entry.dir_port if router_status_entry.dir_port else '' - subwindow.addstr(2, 3, 'nickname: %-25s orport: %-10s %s' % (router_status_entry.nickname, router_status_entry.or_port, dir_port_label), *attr) - subwindow.addstr(2, 4, 'published: %s' % router_status_entry.published.strftime("%H:%M %m/%d/%Y"), *attr) - subwindow.addstr(2, 5, 'flags: %s' % ', '.join(router_status_entry.flags), *attr) - - server_descriptor = controller.get_server_descriptor(fingerprint, None) - - if server_descriptor: - policy_label = server_descriptor.exit_policy.summary() if server_descriptor.exit_policy else 'unknown' - subwindow.addstr(2, 6, 'exit policy: %s' % policy_label, *attr) - subwindow.addstr(38, 4, 'os: %-14s version: %s' % (server_descriptor.operating_system, server_descriptor.tor_version), *attr) - - if server_descriptor.contact: - subwindow.addstr(2, 7, 'contact: %s' % server_descriptor.contact, *attr) - else: - subwindow.addstr(2, 3, 'Multiple matches, possible fingerprints are:', *attr) - - for i, port in enumerate(sorted(matches.keys())): - is_last_line, remaining_relays = i == 3, len(matches) - i - - if not is_last_line or remaining_relays == 1: - subwindow.addstr(2, 4 + i, '%i. or port: %-5s fingerprint: %s' % (i + 1, port, matches[port]), *attr) - else: - subwindow.addstr(2, 4 + i, '... %i more' % remaining_relays, *attr) - - if is_last_line: - break - - # draw the border, with a 'T' pipe if connecting with the scrollbar - - subwindow.box(0, 0, width, DETAILS_HEIGHT + 2) - - if is_scrollbar_visible: - subwindow._addch(1, DETAILS_HEIGHT + 1, curses.ACS_TTEE) - def _draw_line(self, subwindow, x, y, line, is_selected, width, current_time): attr = [CONFIG['attr.connection.category_color'].get(line.entry.get_type(), WHITE)] attr.append(HIGHLIGHT if is_selected else NORMAL) @@ -639,6 +583,7 @@ class ConnectionPanel(nyx.panel.DaemonPanel):
nyx.tracker.get_port_usage_tracker().query(local_ports, remote_ports)
+ def _draw_title(subwindow, entries, showing_details): """ Panel title with the number of connections we presently have. @@ -652,3 +597,60 @@ def _draw_title(subwindow, entries, showing_details): counts = collections.Counter([entry.get_type() for entry in entries]) count_labels = ['%i %s' % (counts[category], category.lower()) for category in Category if counts[category]] subwindow.addstr(0, 0, 'Connections (%s):' % ', '.join(count_labels), HIGHLIGHT) + + +def _draw_details(subwindow, selected): + """ + Shows detailed information about the selected connection. + """ + + attr = (CONFIG['attr.connection.category_color'].get(selected.entry.get_type(), WHITE), BOLD) + + if selected.line_type == LineType.CIRCUIT_HEADER and selected.circuit.status != 'BUILT': + subwindow.addstr(2, 1, 'Building Circuit...', *attr) + else: + address = '<scrubbed>' if selected.entry.is_private() else selected.connection.remote_address + subwindow.addstr(2, 1, 'address: %s:%s' % (address, selected.connection.remote_port), *attr) + subwindow.addstr(2, 2, 'locale: %s' % ('??' if selected.entry.is_private() else (selected.locale if selected.locale else '??')), *attr) + + matches = nyx.tracker.get_consensus_tracker().get_relay_fingerprints(selected.connection.remote_address) + + if not matches: + subwindow.addstr(2, 3, 'No consensus data found', *attr) + elif len(matches) == 1 or selected.connection.remote_port in matches: + controller = tor_controller() + fingerprint = matches.values()[0] if len(matches) == 1 else matches[selected.connection.remote_port] + router_status_entry = controller.get_network_status(fingerprint, None) + + subwindow.addstr(15, 2, 'fingerprint: %s' % fingerprint, *attr) + + if router_status_entry: + dir_port_label = 'dirport: %s' % router_status_entry.dir_port if router_status_entry.dir_port else '' + subwindow.addstr(2, 3, 'nickname: %-25s orport: %-10s %s' % (router_status_entry.nickname, router_status_entry.or_port, dir_port_label), *attr) + subwindow.addstr(2, 4, 'published: %s' % router_status_entry.published.strftime("%H:%M %m/%d/%Y"), *attr) + subwindow.addstr(2, 5, 'flags: %s' % ', '.join(router_status_entry.flags), *attr) + + server_descriptor = controller.get_server_descriptor(fingerprint, None) + + if server_descriptor: + policy_label = server_descriptor.exit_policy.summary() if server_descriptor.exit_policy else 'unknown' + subwindow.addstr(2, 6, 'exit policy: %s' % policy_label, *attr) + subwindow.addstr(38, 4, 'os: %-14s version: %s' % (server_descriptor.operating_system, server_descriptor.tor_version), *attr) + + if server_descriptor.contact: + subwindow.addstr(2, 7, 'contact: %s' % server_descriptor.contact, *attr) + else: + subwindow.addstr(2, 3, 'Multiple matches, possible fingerprints are:', *attr) + + for i, port in enumerate(sorted(matches.keys())): + is_last_line, remaining_relays = i == 3, len(matches) - i + + if not is_last_line or remaining_relays == 1: + subwindow.addstr(2, 4 + i, '%i. or port: %-5s fingerprint: %s' % (i + 1, port, matches[port]), *attr) + else: + subwindow.addstr(2, 4 + i, '... %i more' % remaining_relays, *attr) + + if is_last_line: + break + + subwindow.box(0, 0, subwindow.width, DETAILS_HEIGHT + 2) diff --git a/test/panel/connection.py b/test/panel/connection.py index 8ff08a2..31f00f3 100644 --- a/test/panel/connection.py +++ b/test/panel/connection.py @@ -2,13 +2,78 @@ Unit tests for nyx.panel.connection. """
+import datetime import unittest
+import stem.exit_policy +import stem.version import nyx.panel.connection import test
-from nyx.panel.connection import Category, Entry +from stem.util import connection +from nyx.panel.connection import Category, LineType, Line, Entry from test import require_curses +from mock import Mock, patch + +DETAILS_BUILDING_CIRCUIT = """ ++------------------------------------------------------------------------------+ +| Building Circuit... | +| | +| | +| | +| | +| | +| | ++------------------------------------------------------------------------------+ +""".strip() + +DETAILS_NO_CONSENSUS_DATA = """ ++------------------------------------------------------------------------------+ +| address: 75.119.206.243:22 | +| locale: de | +| No consensus data found | +| | +| | +| | +| | ++------------------------------------------------------------------------------+ +""".strip() + +DETAILS_WHEN_PRIVATE = """ ++------------------------------------------------------------------------------+ +| address: <scrubbed>:22 | +| locale: ?? | +| No consensus data found | +| | +| | +| | +| | ++------------------------------------------------------------------------------+ +""".strip() + +DETAILS_FOR_RELAY = """ ++------------------------------------------------------------------------------+ +| address: 75.119.206.243:22 | +| locale: de fingerprint: B6D83EC2D9E18B0A7A33428F8CFA9C536769E209 | +| nickname: caerSidi orport: 9051 dirport: 9052 | +| published: 17:15 03/01/2012 os: Debian version: 0.2.1.30 | +| flags: Fast, HSDir | +| exit policy: reject 1-65535 | +| contact: spiffy_person@torproject.org | ++------------------------------------------------------------------------------+ +""".strip() + +DETAILS_FOR_MULTIPLE_MATCHES = """ ++------------------------------------------------------------------------------+ +| address: 75.119.206.243:22 | +| locale: de | +| Multiple matches, possible fingerprints are: | +| 1. or port: 52 fingerprint: 1F43EE37A0670301AD9CB555D94AFEC2C89FDE86 | +| 2. or port: 80 fingerprint: B6D83EC2D9E18B0A7A33428F8CFA9C536769E209 | +| 3. or port: 443 fingerprint: E0BD57A11F00041A9789577C53A1B784473669E4 | +| | ++------------------------------------------------------------------------------+ +""".strip()
class MockEntry(Entry): @@ -42,3 +107,67 @@ class TestConnectionPanel(unittest.TestCase): ]
self.assertEqual('Connections (3 inbound, 1 outbound, 1 control):', test.render(nyx.panel.connection._draw_title, entries, False).content) + + @require_curses + def test_draw_details_incomplete_circuit(self): + circ = Mock() + circ.status = 'EXTENDING' + + selected = Line(MockEntry(), LineType.CIRCUIT_HEADER, None, circ, None, None, None) + self.assertEqual(DETAILS_BUILDING_CIRCUIT, test.render(nyx.panel.connection._draw_details, selected).content) + + @require_curses + @patch('nyx.tracker.get_consensus_tracker') + def test_draw_details_no_consensus_data(self, consensus_tracker_mock): + consensus_tracker_mock().get_relay_fingerprints.return_value = None + + selected = Line(MockEntry(), LineType.CONNECTION, connection.Connection('127.0.0.1', 3531, '75.119.206.243', 22, 'tcp', False), None, None, None, 'de') + self.assertEqual(DETAILS_NO_CONSENSUS_DATA, test.render(nyx.panel.connection._draw_details, selected).content) + + @require_curses + @patch('nyx.tracker.get_consensus_tracker') + def test_draw_details_when_private(self, consensus_tracker_mock): + consensus_tracker_mock().get_relay_fingerprints.return_value = None + + selected = Line(MockEntry(is_private = True), LineType.CONNECTION, connection.Connection('127.0.0.1', 3531, '75.119.206.243', 22, 'tcp', False), None, None, None, 'de') + self.assertEqual(DETAILS_WHEN_PRIVATE, test.render(nyx.panel.connection._draw_details, selected).content) + + @require_curses + @patch('nyx.panel.connection.tor_controller') + @patch('nyx.tracker.get_consensus_tracker') + def test_draw_details_for_relay(self, consensus_tracker_mock, tor_controller_mock): + router_status_entry = Mock() + router_status_entry.or_port = 9051 + router_status_entry.dir_port = 9052 + router_status_entry.nickname = 'caerSidi' + router_status_entry.flags = ['Fast', 'HSDir'] + router_status_entry.published = datetime.datetime(2012, 3, 1, 17, 15, 27) + + tor_controller_mock().get_network_status.return_value = router_status_entry + + server_descriptor = Mock() + server_descriptor.exit_policy = stem.exit_policy.ExitPolicy('reject *:*') + server_descriptor.tor_version = stem.version.Version('0.2.1.30') + server_descriptor.operating_system = 'Debian' + server_descriptor.contact = 'spiffy_person@torproject.org' + + tor_controller_mock().get_server_descriptor.return_value = server_descriptor + + consensus_tracker_mock().get_relay_fingerprints.return_value = { + 22: 'B6D83EC2D9E18B0A7A33428F8CFA9C536769E209' + } + + selected = Line(MockEntry(), LineType.CONNECTION, connection.Connection('127.0.0.1', 3531, '75.119.206.243', 22, 'tcp', False), None, None, None, 'de') + self.assertEqual(DETAILS_FOR_RELAY, test.render(nyx.panel.connection._draw_details, selected).content) + + @require_curses + @patch('nyx.tracker.get_consensus_tracker') + def test_draw_details_with_multiple_matches(self, consensus_tracker_mock): + consensus_tracker_mock().get_relay_fingerprints.return_value = { + 52: '1F43EE37A0670301AD9CB555D94AFEC2C89FDE86', + 80: 'B6D83EC2D9E18B0A7A33428F8CFA9C536769E209', + 443: 'E0BD57A11F00041A9789577C53A1B784473669E4', + } + + selected = Line(MockEntry(), LineType.CONNECTION, connection.Connection('127.0.0.1', 3531, '75.119.206.243', 22, 'tcp', False), None, None, None, 'de') + self.assertEqual(DETAILS_FOR_MULTIPLE_MATCHES, test.render(nyx.panel.connection._draw_details, selected).content)
tor-commits@lists.torproject.org