commit 06c3ab5cd39e3584181adaf2545636bff43ee4cf Author: Damian Johnson atagar@torproject.org Date: Mon Jul 4 15:27:26 2016 -0700
Test _draw_entries()
Breaking up our log panel's draw() method further and adding more coverage. --- nyx/panel/log.py | 71 ++++++++++++++++++++++-------------------- test/panel/log.py | 93 ++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 117 insertions(+), 47 deletions(-)
diff --git a/nyx/panel/log.py b/nyx/panel/log.py index bc229d9..5d4c36e 100644 --- a/nyx/panel/log.py +++ b/nyx/panel/log.py @@ -255,46 +255,22 @@ class LogPanel(nyx.panel.DaemonPanel): def draw(self, subwindow): scroll = self._scroller.location(self._last_content_height, subwindow.height - 1)
- event_log = list(self._event_log_paused if self.is_paused() else self._event_log) event_filter = self._filter.clone() event_types = list(self._event_types) last_content_height = self._last_content_height show_duplicates = self._show_duplicates
+ event_log = self._event_log_paused if self.is_paused() else self._event_log + event_log = filter(lambda entry: event_filter.match(entry.display_message), event_log) + event_log = filter(lambda entry: not entry.is_duplicate or show_duplicates, event_log) + is_scrollbar_visible = last_content_height > subwindow.height - 1
if is_scrollbar_visible: subwindow.scrollbar(1, scroll, last_content_height - 1)
x, y = 3 if is_scrollbar_visible else 1, 1 - scroll - - # group entries by date, filtering out those that aren't visible - - day_to_entries, today = {}, nyx.log.day_count(time.time()) - - for entry in event_log: - if entry.is_duplicate and not show_duplicates: - continue # deduplicated message - elif not event_filter.match(entry.display_message): - continue # filter doesn't match log message - - day_to_entries.setdefault(entry.day_count(), []).append(entry) - - for day in sorted(day_to_entries.keys(), reverse = True): - if day == today: - for entry in day_to_entries[day]: - y = _draw_entry(subwindow, x, y, entry, show_duplicates) - else: - original_y, y = y, y + 1 - - for entry in day_to_entries[day]: - y = _draw_entry(subwindow, x, y, entry, show_duplicates) - - subwindow.box(original_y, x - 1, subwindow.width - x + 1, y - original_y + 1, YELLOW, BOLD) - time_label = time.strftime(' %B %d, %Y ', time.localtime(day_to_entries[day][0].timestamp)) - subwindow.addstr(x + 1, original_y, time_label, YELLOW, BOLD) - - y += 1 + y = _draw_entries(subwindow, x, y, event_log, show_duplicates)
# drawing the title after the content, so we'll clear content from the top line
@@ -382,9 +358,38 @@ def _draw_title(subwindow, event_types, event_filter): subwindow.addstr(0, 0, title, HIGHLIGHT)
-def _draw_entry(subwindow, x, y, entry, show_duplicates): +def _draw_entries(subwindow, x, y, event_log, show_duplicates): + """ + Presents a list of log entries, grouped by the day they appeared. + """ + + day_to_entries, today = {}, nyx.log.day_count(time.time()) + + for entry in event_log: + day_to_entries.setdefault(entry.day_count(), []).append(entry) + + for day in sorted(day_to_entries.keys(), reverse = True): + if day == today: + for entry in day_to_entries[day]: + y = _draw_entry(subwindow, x, y, subwindow.width, entry, show_duplicates) + else: + original_y, y = y, y + 1 + + for entry in day_to_entries[day]: + y = _draw_entry(subwindow, x, y, subwindow.width - 1, entry, show_duplicates) + + subwindow.box(original_y, x - 1, subwindow.width - x + 1, y - original_y + 1, YELLOW, BOLD) + time_label = time.strftime(' %B %d, %Y ', time.localtime(day_to_entries[day][0].timestamp)) + subwindow.addstr(x + 1, original_y, time_label, YELLOW, BOLD) + + y += 1 + + return y + + +def _draw_entry(subwindow, x, y, width, entry, show_duplicates): """ - Presents a log entry with line wrapping. + Presents an individual log entry with line wrapping. """
color = CONFIG['attr.log_color'].get(entry.type, WHITE) @@ -392,12 +397,12 @@ def _draw_entry(subwindow, x, y, entry, show_duplicates): min_x = x + 2
for line in entry.display_message.splitlines(): - x, y = subwindow.addstr_wrap(x, y, line, subwindow.width, min_x, boldness, color) + x, y = subwindow.addstr_wrap(x, y, line, width, min_x, boldness, color)
if entry.duplicates and not show_duplicates: duplicate_count = len(entry.duplicates) - 1 plural = 's' if duplicate_count > 1 else '' duplicate_msg = ' [%i duplicate%s hidden]' % (duplicate_count, plural) - x, y = subwindow.addstr_wrap(x, y, duplicate_msg, subwindow.width, min_x, GREEN, BOLD) + x, y = subwindow.addstr_wrap(x, y, duplicate_msg, width, min_x, GREEN, BOLD)
return y + 1 diff --git a/test/panel/log.py b/test/panel/log.py index 9a408f4..4610bff 100644 --- a/test/panel/log.py +++ b/test/panel/log.py @@ -2,6 +2,7 @@ Unit tests for nyx.panel.log. """
+import time import unittest
import nyx.panel.log @@ -9,13 +10,60 @@ import test
from nyx.log import LogEntry, LogFilters from test import require_curses +from mock import patch, Mock
EXPECTED_WRAPPED_MSG = """\ -[NOTICE] ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho +16:41:37 [NOTICE] ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum, ho hum... """.rstrip()
+EXPECTED_ENTRIES = """\ +16:41:37 [NYX_WARNING] Tor's geoip database is unavailable. +16:41:37 [NYX_NOTICE] No nyxrc loaded, using defaults. You can customize nyx by + placing a configuration file at /home/atagar/.nyx/nyxrc (see the nyxrc.sample + for its options). +16:41:37 [NOTICE] New control connection opened from 127.0.0.1. +16:41:37 [NOTICE] Opening OR listener on 0.0.0.0:7000 +16:41:37 [NOTICE] Opening Control listener on 127.0.0.1:9051 +16:41:37 [NOTICE] Opening Socks listener on 127.0.0.1:9050 +16:41:37 [NOTICE] Tor v0.2.9.0-alpha-dev (git-44ea3dc3311564a9) running on Linux + with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4. +16:41:37 [NOTICE] Tor 0.2.9.0-alpha-dev (git-44ea3dc3311564a9) opening log file. +""".rstrip() + +EXPECTED_ENTRIES_WITH_BORDER = """\ +|October 26, 2011 | +|6:41:37 [NYX_WARNING] Tor's geoip database is unavailable. | +|6:41:37 [NYX_NOTICE] No nyxrc loaded, using defaults. You can customize nyx by| +| placing a configuration file at /home/atagar/.nyx/nyxrc (see the nyxrc.sample| +| for its options). | +|6:41:37 [NOTICE] New control connection opened from 127.0.0.1. | +|6:41:37 [NOTICE] Opening OR listener on 0.0.0.0:7000 | +|6:41:37 [NOTICE] Opening Control listener on 127.0.0.1:9051 | +|6:41:37 [NOTICE] Opening Socks listener on 127.0.0.1:9050 | +|6:41:37 [NOTICE] Tor v0.2.9.0-alpha-dev (git-44ea3dc3311564a9) running on | +| Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4. | +|6:41:37 [NOTICE] Tor 0.2.9.0-alpha-dev (git-44ea3dc3311564a9) opening log | ++------------------------------------------------------------------------------+ +""".rstrip() + +NOW = 467656897.08663 +TIME_STRUCT = time.gmtime(NOW) + + +def entries(): + return [ + LogEntry(NOW, 'NYX_WARNING', "Tor's geoip database is unavailable."), + LogEntry(NOW, 'NYX_NOTICE', 'No nyxrc loaded, using defaults. You can customize nyx by placing a configuration file at /home/atagar/.nyx/nyxrc (see the nyxrc.sample for its options).'), + LogEntry(NOW, 'NOTICE', 'New control connection opened from 127.0.0.1.'), + LogEntry(NOW, 'NOTICE', 'Opening OR listener on 0.0.0.0:7000'), + LogEntry(NOW, 'NOTICE', 'Opening Control listener on 127.0.0.1:9051'), + LogEntry(NOW, 'NOTICE', 'Opening Socks listener on 127.0.0.1:9050'), + LogEntry(NOW, 'NOTICE', 'Tor v0.2.9.0-alpha-dev (git-44ea3dc3311564a9) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.'), + LogEntry(NOW, 'NOTICE', 'Tor 0.2.9.0-alpha-dev (git-44ea3dc3311564a9) opening log file.'), + ] +
class TestLogPanel(unittest.TestCase): @require_curses @@ -38,27 +86,44 @@ class TestLogPanel(unittest.TestCase): self.assertEqual('Events (NOTICE-ERR, filter: stuff*):', rendered.content)
@require_curses + @patch('time.localtime', Mock(return_value = TIME_STRUCT)) def test_draw_entry(self): - entry = LogEntry(1467656897.08663, 'NOTICE', 'feeding sulfur to baby dragons is just mean...') - rendered = test.render(nyx.panel.log._draw_entry, 0, 0, entry, True) - self.assertEqual('[NOTICE] feeding sulfur to baby dragons is just mean...', rendered.content.split(' ', 1)[1]) + entry = LogEntry(NOW, 'NOTICE', 'feeding sulfur to baby dragons is just mean...') + rendered = test.render(nyx.panel.log._draw_entry, 0, 0, 80, entry, True) + self.assertEqual('16:41:37 [NOTICE] feeding sulfur to baby dragons is just mean...', rendered.content)
@require_curses + @patch('time.localtime', Mock(return_value = TIME_STRUCT)) def test_draw_entry_that_wraps(self): - entry = LogEntry(1467656897.08663, 'NOTICE', 'ho hum%s...' % (', ho hum' * 20)) - rendered = test.render(nyx.panel.log._draw_entry, 0, 0, entry, True) - self.assertEqual(EXPECTED_WRAPPED_MSG, rendered.content.split(' ', 1)[1]) + entry = LogEntry(NOW, 'NOTICE', 'ho hum%s...' % (', ho hum' * 20)) + rendered = test.render(nyx.panel.log._draw_entry, 0, 0, 80, entry, True) + self.assertEqual(EXPECTED_WRAPPED_MSG, rendered.content)
@require_curses + @patch('time.localtime', Mock(return_value = TIME_STRUCT)) def test_draw_entry_with_duplicates(self): - entry = LogEntry(1467656897.08663, 'NOTICE', 'feeding sulfur to baby dragons is just mean...') + entry = LogEntry(NOW, 'NOTICE', 'feeding sulfur to baby dragons is just mean...') entry.duplicates = [1, 2] # only care about the count, not the content - rendered = test.render(nyx.panel.log._draw_entry, 0, 0, entry, True) - self.assertEqual('[NOTICE] feeding sulfur to baby dragons is just mean...', rendered.content.split(' ', 1)[1]) + rendered = test.render(nyx.panel.log._draw_entry, 0, 0, 80, entry, True) + self.assertEqual('16:41:37 [NOTICE] feeding sulfur to baby dragons is just mean...', rendered.content)
- rendered = test.render(nyx.panel.log._draw_entry, 0, 0, entry, False) - self.assertEqual('[NOTICE] feeding sulfur to baby dragons is just mean... [1 duplicate\n hidden]', rendered.content.split(' ', 1)[1]) + rendered = test.render(nyx.panel.log._draw_entry, 0, 0, 80, entry, False) + self.assertEqual('16:41:37 [NOTICE] feeding sulfur to baby dragons is just mean... [1 duplicate\n hidden]', rendered.content)
entry.duplicates = [1, 2, 3, 4, 5, 6] - rendered = test.render(nyx.panel.log._draw_entry, 0, 0, entry, False) - self.assertEqual('[NOTICE] feeding sulfur to baby dragons is just mean... [5 duplicates\n hidden]', rendered.content.split(' ', 1)[1]) + rendered = test.render(nyx.panel.log._draw_entry, 0, 0, 80, entry, False) + self.assertEqual('16:41:37 [NOTICE] feeding sulfur to baby dragons is just mean... [5 duplicates\n hidden]', rendered.content) + + @require_curses + @patch('time.localtime', Mock(return_value = TIME_STRUCT)) + @patch('nyx.log.day_count', Mock(return_value = 5)) + def test_draw_entries(self): + rendered = test.render(nyx.panel.log._draw_entries, 0, 0, entries(), True) + self.assertEqual(EXPECTED_ENTRIES, rendered.content) + + @require_curses + @patch('time.localtime', Mock(return_value = TIME_STRUCT)) + @patch('time.strftime', Mock(return_value = 'October 26, 2011')) + def test_draw_entries_day_dividers(self): + rendered = test.render(nyx.panel.log._draw_entries, 0, 0, entries(), True) + self.assertEqual(EXPECTED_ENTRIES_WITH_BORDER, rendered.content)
tor-commits@lists.torproject.org