From 409b59970ce486b0cab8f72b942ad519143b3797 Mon Sep 17 00:00:00 2001 From: laixintao Date: Sun, 8 Oct 2023 00:32:21 +0800 Subject: [PATCH 1/2] add tests on flamegraph --- flameshow/render/flamegraph.py | 10 ++++- tests/test_cli_click.py | 7 +++- tests/test_colors.py | 3 ++ tests/test_main.py | 19 +++++++++ tests/test_render/test_flamegraph.py | 59 ++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 4 deletions(-) diff --git a/flameshow/render/flamegraph.py b/flameshow/render/flamegraph.py index 01e256a..b3171c1 100644 --- a/flameshow/render/flamegraph.py +++ b/flameshow/render/flamegraph.py @@ -164,6 +164,8 @@ def render_line(self, y: int) -> Strip: line = self.profile.lines[y] if not self.frame_maps: + # never should happen + # pragma: no cover raise RenderException("frame_maps is not init yet!") segments = [] @@ -171,7 +173,8 @@ def render_line(self, y: int) -> Strip: for frame in line: frame_maps = self.frame_maps.get(frame._id) if not frame_maps: - continue + # never should happen + continue # pragma: no cover frame_map = frame_maps[self.sample_index] my_width = frame_map.width if not my_width: @@ -185,7 +188,10 @@ def render_line(self, y: int) -> Strip: segments.append(Segment(" " * pre_pad)) cursor += pre_pad elif pre_pad < 0: - raise Exception("Prepad is negative! {}".format(pre_pad)) + # never should happen + raise Exception( + "Prepad is negative! {}".format(pre_pad) + ) # pragma: no cover if len(text) < my_width: text += " " * (my_width - len(text)) diff --git a/tests/test_cli_click.py b/tests/test_cli_click.py index c4bc6f9..9360e1d 100644 --- a/tests/test_cli_click.py +++ b/tests/test_cli_click.py @@ -1,6 +1,9 @@ +import os +from unittest.mock import MagicMock, patch + from click.testing import CliRunner -from flameshow.main import main, ensure_tty -from unittest.mock import patch, MagicMock + +from flameshow.main import ensure_tty, main def test_print_version(): diff --git a/tests/test_colors.py b/tests/test_colors.py index 60237ca..619149e 100644 --- a/tests/test_colors.py +++ b/tests/test_colors.py @@ -13,6 +13,9 @@ def test_linaer_color_platte(): assert isinstance(color2, Color) + for key in range(999): + platte.get_color(key) + def test_flamegraph_random_color_platte(): platte = flamegraph_random_color_platte diff --git a/tests/test_main.py b/tests/test_main.py index e69de29..1aed773 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -0,0 +1,19 @@ +import logging +from flameshow.main import setup_log +import os + +from unittest.mock import patch + + +def test_run_app_with_verbose_logging(data_dir): + # cleanup logfile first + path = data_dir / "._pytest_flameshow.log" + try: + os.remove(path) + except: # noqa + pass + + with patch.object(logging, "basicConfig") as mock_config: + setup_log(True, logging.DEBUG, path) + + mock_config.assert_called_once() diff --git a/tests/test_render/test_flamegraph.py b/tests/test_render/test_flamegraph.py index 32d61a7..8f79ce1 100644 --- a/tests/test_render/test_flamegraph.py +++ b/tests/test_render/test_flamegraph.py @@ -691,3 +691,62 @@ def test_flamegraph_render_on_mouse_move(): message = args[0] assert message.by_mouse == True assert message.frame._id == 1 + + # move down, not hover on any lines + flamegraph_widget.post_message = MagicMock() + flamegraph_widget.on_mouse_move( + MouseMove( + x=0, + y=3, + delta_x=0, + delta_y=0, + button=False, + shift=False, + meta=False, + ctrl=False, + ) + ) + args = flamegraph_widget.post_message.assert_not_called() + + +def test_flamegraph_render_line_with_some_width_is_0(): + id_store = {} + root = create_frame( + { + "id": 0, + "values": [10], + "children": [ + {"id": 2, "values": [3], "children": []}, + { + "id": 1, + "values": [2], + "children": [ + {"id": 3, "values": [1], "children": []}, + ], + }, + {"id": 4, "values": [0.1], "children": []}, + ], + }, + id_store, + ) + + p = Profile( + filename="abc", + root_stack=root, + highest_lines=1, + total_sample=2, + sample_types=[SampleType("samples", "count")], + id_store=id_store, + ) + flamegraph_widget = FlameGraph(p, 0, -1, 0) + flamegraph_widget.frame_maps = flamegraph_widget.generate_frame_maps( + 10, focused_stack_id=0 + ) + + strip = flamegraph_widget.render_line( + 1, + ) + + line_strings = [seg.text for seg in strip._segments] + + assert line_strings == ["▏", "no", "▏", "n"] From e3c2367a2d2e1596523ead899089892bf00fcbec Mon Sep 17 00:00:00 2001 From: laixintao Date: Sun, 8 Oct 2023 00:44:43 +0800 Subject: [PATCH 2/2] test click mouse --- tests/test_render/test_flamegraph.py | 91 ++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 12 deletions(-) diff --git a/tests/test_render/test_flamegraph.py b/tests/test_render/test_flamegraph.py index 8f79ce1..6b64193 100644 --- a/tests/test_render/test_flamegraph.py +++ b/tests/test_render/test_flamegraph.py @@ -1,7 +1,7 @@ from unittest.mock import MagicMock import pytest -from textual.events import MouseMove +from textual.events import Click, MouseMove from flameshow.exceptions import RenderException from flameshow.models import Frame @@ -636,18 +636,17 @@ def test_flamegraph_render_on_mouse_move(): flamegraph_widget.frame_maps = flamegraph_widget.generate_frame_maps(10, 0) flamegraph_widget.post_message = MagicMock() - flamegraph_widget.on_mouse_move( - MouseMove( - x=2, - y=1, - delta_x=0, - delta_y=0, - button=False, - shift=False, - meta=False, - ctrl=False, - ) + mouse_event = MouseMove( + x=2, + y=1, + delta_x=0, + delta_y=0, + button=False, + shift=False, + meta=False, + ctrl=False, ) + flamegraph_widget.on_mouse_move(mouse_event) flamegraph_widget.post_message.assert_called_once() args = flamegraph_widget.post_message.call_args[0] @@ -655,6 +654,10 @@ def test_flamegraph_render_on_mouse_move(): assert message.by_mouse == True assert message.frame._id == 2 + assert flamegraph_widget.focused_stack_id == 0 + flamegraph_widget.handle_click_frame(mouse_event) + assert flamegraph_widget.focused_stack_id == 2 + # move to lines that empty flamegraph_widget.post_message = MagicMock() flamegraph_widget.on_mouse_move( @@ -750,3 +753,67 @@ def test_flamegraph_render_line_with_some_width_is_0(): line_strings = [seg.text for seg in strip._segments] assert line_strings == ["▏", "no", "▏", "n"] + + +def test_flamegraph_render_line_with_focused_frame(): + id_store = {} + root = create_frame( + { + "id": 0, + "values": [10], + "children": [ + {"id": 1, "values": [3], "children": []}, + {"id": 4, "values": [1], "children": []}, + { + "id": 2, + "values": [6], + "children": [ + {"id": 3, "values": [1], "children": []}, + ], + }, + ], + }, + id_store, + ) + + p = Profile( + filename="abc", + root_stack=root, + highest_lines=1, + total_sample=2, + sample_types=[SampleType("samples", "count")], + id_store=id_store, + ) + flamegraph_widget = FlameGraph(p, 2, -1, 0) + flamegraph_widget.frame_maps = flamegraph_widget.generate_frame_maps( + 10, focused_stack_id=2 + ) + + strip = flamegraph_widget.render_line( + 1, + ) + + line_strings = [seg.text for seg in strip._segments] + + assert line_strings == ["▏", "node-2 "] + + flamegraph_widget.post_message = MagicMock() + + flamegraph_widget.on_mouse_move( + MouseMove( + x=0, + y=1, + delta_x=0, + delta_y=0, + button=False, + shift=False, + meta=False, + ctrl=False, + ) + ) + + flamegraph_widget.post_message.assert_called_once() + args = flamegraph_widget.post_message.call_args[0] + message = args[0] + assert message.by_mouse == True + assert message.frame._id == 2