[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [nyx/master] Test for drawing a blank subgraph
commit 7719621a1e184e5e94fec94a06a70ded0d2171e0
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sat Jun 25 12:34:24 2016 -0700
Test for drawing a blank subgraph
Not an overly useful test but first step in breaking these into functions and
adding test coverage.
---
nyx/panel/graph.py | 216 ++++++++++++++++++++++++++--------------------------
test/panel/graph.py | 30 ++++++++
2 files changed, 140 insertions(+), 106 deletions(-)
diff --git a/nyx/panel/graph.py b/nyx/panel/graph.py
index d3ed768..68c136a 100644
--- a/nyx/panel/graph.py
+++ b/nyx/panel/graph.py
@@ -556,152 +556,156 @@ class GraphPanel(nyx.panel.Panel):
subwindow.addstr(0, 0, attr.stat.title(subwindow.width), HIGHLIGHT)
- self._draw_subgraph(subwindow, attr, attr.stat.primary, 0, PRIMARY_COLOR)
- self._draw_subgraph(subwindow, attr, attr.stat.secondary, attr.subgraph_width, SECONDARY_COLOR)
+ _draw_subgraph(subwindow, attr, attr.stat.primary, 0, PRIMARY_COLOR)
+ _draw_subgraph(subwindow, attr, attr.stat.secondary, attr.subgraph_width, SECONDARY_COLOR)
if attr.stat.stat_type() == GraphStat.BANDWIDTH and accounting_stats:
_draw_accounting_stats(subwindow, DEFAULT_CONTENT_HEIGHT + attr.subgraph_height - 2, accounting_stats)
- def _draw_subgraph(self, subwindow, attr, data, x, color):
- # Concering our subgraph colums, the y-axis label can be at most six
- # characters, with two spaces of padding on either side of the graph.
- # Starting with the smallest size, then possibly raise it after determing
- # the y_axis_labels.
+ def _update_accounting(self, event):
+ if not CONFIG['features.graph.bw.accounting.show']:
+ self._accounting_stats = None
+ elif not self._accounting_stats or time.time() - self._accounting_stats.retrieved >= ACCOUNTING_RATE:
+ old_accounting_stats = self._accounting_stats
+ self._accounting_stats = tor_controller().get_accounting_stats(None)
- subgraph_columns = attr.subgraph_width - 8
- min_bound, max_bound = self._get_graph_bounds(attr, data, subgraph_columns)
+ if not self.is_paused():
+ # if we either added or removed accounting info then redraw the whole
+ # screen to account for resizing
- x_axis_labels = self._get_x_axis_labels(attr, subgraph_columns)
- y_axis_labels = self._get_y_axis_labels(attr, data, min_bound, max_bound)
- subgraph_columns = max(subgraph_columns, attr.subgraph_width - max([len(label) for label in y_axis_labels.values()]) - 2)
- axis_offset = max([len(label) for label in y_axis_labels.values()])
+ if bool(old_accounting_stats) != bool(self._accounting_stats):
+ nyx.controller.get_controller().redraw()
- subwindow.addstr(x, 1, data.header(attr.subgraph_width), color, BOLD)
+ def _update_stats(self, event):
+ for stat in self._stats.values():
+ stat.bandwidth_event(event)
- for x_offset, label in x_axis_labels.items():
- if attr.right_to_left:
- subwindow.addstr(x + attr.subgraph_width - x_offset, attr.subgraph_height, label, color)
- else:
- subwindow.addstr(x + x_offset + axis_offset, attr.subgraph_height, label, color)
+ if self.displayed_stat:
+ param = self._stats[self.displayed_stat]
+ update_rate = INTERVAL_SECONDS[self.update_interval]
- for y, label in y_axis_labels.items():
- subwindow.addstr(x, y, label, color)
+ if param.primary.tick % update_rate == 0:
+ self.redraw(True)
- for col in range(subgraph_columns):
- column_count = int(data.values[attr.interval][col]) - min_bound
- column_height = int(min(attr.subgraph_height - 2, (attr.subgraph_height - 2) * column_count / (max(1, max_bound) - min_bound)))
- for row in range(column_height):
- if attr.right_to_left:
- subwindow.addstr(x + attr.subgraph_width - col - 1, attr.subgraph_height - 1 - row, ' ', color, HIGHLIGHT)
- else:
- subwindow.addstr(x + col + axis_offset + 1, attr.subgraph_height - 1 - row, ' ', color, HIGHLIGHT)
+def _draw_subgraph(subwindow, attr, data, x, color):
+ # Concering our subgraph colums, the y-axis label can be at most six
+ # characters, with two spaces of padding on either side of the graph.
+ # Starting with the smallest size, then possibly raise it after determing
+ # the y_axis_labels.
- def _get_graph_bounds(self, attr, data, subgraph_columns):
- """
- Provides the range the graph shows (ie, its minimum and maximum value).
- """
+ subgraph_columns = attr.subgraph_width - 8
+ min_bound, max_bound = _get_graph_bounds(attr, data, subgraph_columns)
- min_bound, max_bound = 0, 0
- values = data.values[attr.interval][:subgraph_columns]
+ x_axis_labels = _x_axis_labels(attr.interval, subgraph_columns)
+ y_axis_labels = _y_axis_labels(attr.subgraph_height, data, min_bound, max_bound)
+ subgraph_columns = max(subgraph_columns, attr.subgraph_width - max([len(label) for label in y_axis_labels.values()]) - 2)
+ axis_offset = max([len(label) for label in y_axis_labels.values()])
- if attr.bounds_type == Bounds.GLOBAL_MAX:
- max_bound = data.max_value[attr.interval]
- elif subgraph_columns > 0:
- max_bound = max(values) # local maxima
+ subwindow.addstr(x, 1, data.header(attr.subgraph_width), color, BOLD)
- if attr.bounds_type == Bounds.TIGHT and subgraph_columns > 0:
- min_bound = min(values)
+ for x_offset, label in x_axis_labels.items():
+ if attr.right_to_left:
+ subwindow.addstr(x + attr.subgraph_width - x_offset, attr.subgraph_height, label, color)
+ else:
+ subwindow.addstr(x + x_offset + axis_offset, attr.subgraph_height, label, color)
- # if the max = min pick zero so we still display something
+ for y, label in y_axis_labels.items():
+ subwindow.addstr(x, y, label, color)
- if min_bound == max_bound:
- min_bound = 0
+ for col in range(subgraph_columns):
+ column_count = int(data.values[attr.interval][col]) - min_bound
+ column_height = int(min(attr.subgraph_height - 2, (attr.subgraph_height - 2) * column_count / (max(1, max_bound) - min_bound)))
- return min_bound, max_bound
+ for row in range(column_height):
+ if attr.right_to_left:
+ subwindow.addstr(x + attr.subgraph_width - col - 1, attr.subgraph_height - 1 - row, ' ', color, HIGHLIGHT)
+ else:
+ subwindow.addstr(x + col + axis_offset + 1, attr.subgraph_height - 1 - row, ' ', color, HIGHLIGHT)
- def _get_y_axis_labels(self, attr, data, min_bound, max_bound):
- """
- Provides the labels for the y-axis. This is a mapping of the position it
- should be drawn at to its text.
- """
- y_axis_labels = {
- 2: data.y_axis_label(max_bound),
- attr.subgraph_height - 1: data.y_axis_label(min_bound),
- }
+def _get_graph_bounds(attr, data, subgraph_columns):
+ """
+ Provides the range the graph shows (ie, its minimum and maximum value).
+ """
- ticks = (attr.subgraph_height - 5) / 2
+ min_bound, max_bound = 0, 0
+ values = data.values[attr.interval][:subgraph_columns]
- for i in range(ticks):
- row = attr.subgraph_height - (2 * i) - 5
+ if attr.bounds_type == Bounds.GLOBAL_MAX:
+ max_bound = data.max_value[attr.interval]
+ elif subgraph_columns > 0:
+ max_bound = max(values) # local maxima
- if attr.subgraph_height % 2 == 0 and i >= (ticks / 2):
- row -= 1 # make extra gap be in the middle when we're an even size
+ if attr.bounds_type == Bounds.TIGHT and subgraph_columns > 0:
+ min_bound = min(values)
- val = (max_bound - min_bound) * (attr.subgraph_height - row - 3) / (attr.subgraph_height - 3)
+ # if the max = min pick zero so we still display something
- if val not in (min_bound, max_bound):
- y_axis_labels[row + 2] = data.y_axis_label(val)
+ if min_bound == max_bound:
+ min_bound = 0
- return y_axis_labels
+ return min_bound, max_bound
- def _get_x_axis_labels(self, attr, subgraph_columns):
- """
- Provides the labels for the x-axis. We include the units for only its first
- value, then bump the precision for subsequent units. For example...
- 10s, 20, 30, 40, 50, 1m, 1.1, 1.3, 1.5
- """
+def _x_axis_labels(interval, subgraph_columns):
+ """
+ Provides the labels for the x-axis. We include the units for only its first
+ value, then bump the precision for subsequent units. For example...
- x_axis_labels = {}
+ 10s, 20, 30, 40, 50, 1m, 1.1, 1.3, 1.5
+ """
- interval_sec = INTERVAL_SECONDS[attr.interval]
- interval_spacing = 10 if subgraph_columns >= WIDE_LABELING_GRAPH_COL else 5
- units_label, decimal_precision = None, 0
+ x_axis_labels = {}
- for i in range((subgraph_columns - 4) / interval_spacing):
- x = (i + 1) * interval_spacing
- time_label = str_tools.time_label(x * interval_sec, decimal_precision)
+ interval_sec = INTERVAL_SECONDS[interval]
+ interval_spacing = 10 if subgraph_columns >= WIDE_LABELING_GRAPH_COL else 5
+ units_label, decimal_precision = None, 0
- if not units_label:
- units_label = time_label[-1]
- elif units_label != time_label[-1]:
- # upped scale so also up precision of future measurements
- units_label = time_label[-1]
- decimal_precision += 1
- else:
- # if constrained on space then strips labeling since already provided
- time_label = time_label[:-1]
+ for i in range((subgraph_columns - 4) / interval_spacing):
+ x = (i + 1) * interval_spacing
+ time_label = str_tools.time_label(x * interval_sec, decimal_precision)
- x_axis_labels[x] = time_label
+ if not units_label:
+ units_label = time_label[-1]
+ elif units_label != time_label[-1]:
+ # upped scale so also up precision of future measurements
+ units_label = time_label[-1]
+ decimal_precision += 1
+ else:
+ # if constrained on space then strips labeling since already provided
+ time_label = time_label[:-1]
- return x_axis_labels
+ x_axis_labels[x] = time_label
- def _update_accounting(self, event):
- if not CONFIG['features.graph.bw.accounting.show']:
- self._accounting_stats = None
- elif not self._accounting_stats or time.time() - self._accounting_stats.retrieved >= ACCOUNTING_RATE:
- old_accounting_stats = self._accounting_stats
- self._accounting_stats = tor_controller().get_accounting_stats(None)
+ return x_axis_labels
- if not self.is_paused():
- # if we either added or removed accounting info then redraw the whole
- # screen to account for resizing
- if bool(old_accounting_stats) != bool(self._accounting_stats):
- nyx.controller.get_controller().redraw()
+def _y_axis_labels(subgraph_height, data, min_bound, max_bound):
+ """
+ Provides the labels for the y-axis. This is a mapping of the position it
+ should be drawn at to its text.
+ """
- def _update_stats(self, event):
- for stat in self._stats.values():
- stat.bandwidth_event(event)
+ y_axis_labels = {
+ 2: data.y_axis_label(max_bound),
+ subgraph_height - 1: data.y_axis_label(min_bound),
+ }
- if self.displayed_stat:
- param = self._stats[self.displayed_stat]
- update_rate = INTERVAL_SECONDS[self.update_interval]
+ ticks = (subgraph_height - 5) / 2
- if param.primary.tick % update_rate == 0:
- self.redraw(True)
+ for i in range(ticks):
+ row = subgraph_height - (2 * i) - 5
+
+ if subgraph_height % 2 == 0 and i >= (ticks / 2):
+ row -= 1 # make extra gap be in the middle when we're an even size
+
+ val = (max_bound - min_bound) * (subgraph_height - row - 3) / (subgraph_height - 3)
+
+ if val not in (min_bound, max_bound):
+ y_axis_labels[row + 2] = data.y_axis_label(val)
+
+ return y_axis_labels
def _draw_accounting_stats(subwindow, y, accounting):
diff --git a/test/panel/graph.py b/test/panel/graph.py
index f2eca4b..26fd7da 100644
--- a/test/panel/graph.py
+++ b/test/panel/graph.py
@@ -7,12 +7,23 @@ import unittest
import stem.control
+import nyx.curses
import nyx.panel.graph
import test
from test import require_curses
from mock import patch
+EXPECTED_BLANK_GRAPH = """
+Download:
+0 b
+
+
+
+0 b
+ 5s 10 15
+""".rstrip()
+
EXPECTED_ACCOUNTING = """
Accounting (awake) Time to reset: 01:02
37.7 Kb / 842.0 Kb 16.0 Kb / 74.1 Kb
@@ -22,6 +33,25 @@ Accounting (awake) Time to reset: 01:02
class TestGraph(unittest.TestCase):
@require_curses
@patch('nyx.panel.graph.tor_controller')
+ def test_draw_subgraph_blank(self, tor_controller_mock):
+ tor_controller_mock().get_info.return_value = None
+
+ attr = nyx.panel.graph.DrawAttributes(
+ stat = None,
+ subgraph_height = 7,
+ subgraph_width = 30,
+ interval = nyx.panel.graph.Interval.EACH_SECOND,
+ bounds_type = nyx.panel.graph.Bounds.LOCAL_MAX,
+ right_to_left = False,
+ )
+
+ data = nyx.panel.graph.BandwidthStats()
+
+ rendered = test.render(nyx.panel.graph._draw_subgraph, attr, data.primary, 0, nyx.curses.Color.CYAN)
+ self.assertEqual(EXPECTED_BLANK_GRAPH, rendered.content)
+
+ @require_curses
+ @patch('nyx.panel.graph.tor_controller')
def test_draw_accounting_stats(self, tor_controller_mock):
tor_controller_mock().is_alive.return_value = True
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits