aboutsummaryrefslogtreecommitdiff
path: root/heatmaps/heat_map_test.py
diff options
context:
space:
mode:
authorTiancong Wang <tcwang@google.com>2019-05-06 15:42:43 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-05-17 18:38:15 -0700
commit3f06bf5fa1c53aa42959d351accc8888eb329343 (patch)
tree86be399d8cf24ff607f30a21f8b31634bffe4e4a /heatmaps/heat_map_test.py
parentadb9f7a366cb5e8ae5eb5c860da191e0418e8901 (diff)
downloadtoolchain-utils-3f06bf5fa1c53aa42959d351accc8888eb329343.tar.gz
toolchain-utils: Improve heatmap tool.
The overall goal of this patch is to improve heatmap tool in a way that facilitates the tool to be integrated into crosperf. The patch needs to make sure the heat_map.py is not only able to run as a standalone tool, but also is compatible to crosperf. It also adds functionality to the heatmap that when the address range of huge page (offset within the text section) is provided, the heatmap displays symbols within and outside of the region with different colors. This patch adds following improvements: 1. It adds support in heat_map.py that skips copying perf.data into the chroot again, if the provided path to perf.data is within a chroot. 2. It adds support in heatmap_generator.py to take in a range of huge page as (start, end). Update corresponding unit test. 3. It adds extensive unit tests for heat_map.py. The unit test tests both each functions and also makes sure it run as a standalone tool. BUG=chromium:956109 TEST=Tested locally and pass unit tests. Change-Id: I8008da51cceb0ad90df29042faf7a9d91d04f4b1 Reviewed-on: https://chromium-review.googlesource.com/1582523 Commit-Ready: Tiancong Wang <tcwang@google.com> Tested-by: Tiancong Wang <tcwang@google.com> Reviewed-by: Tiancong Wang <tcwang@google.com>
Diffstat (limited to 'heatmaps/heat_map_test.py')
-rwxr-xr-xheatmaps/heat_map_test.py157
1 files changed, 157 insertions, 0 deletions
diff --git a/heatmaps/heat_map_test.py b/heatmaps/heat_map_test.py
new file mode 100755
index 00000000..c6474670
--- /dev/null
+++ b/heatmaps/heat_map_test.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+#
+# Copyright 2019 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for heat_map.py."""
+
+from __future__ import print_function
+
+import mock
+import unittest
+
+import os
+
+from cros_utils import command_executer
+
+import heat_map
+
+
+def make_heatmap(chromeos_root='/path/to/fake/chromeos_root/',
+ perf_data='/any_path/perf.data'):
+ return heat_map.HeatMapProducer(chromeos_root, perf_data, None, None, '')
+
+
+def fake_mkdtemp(prefix):
+ """Mock tempfile.mkdtemp() by just create a pathname."""
+ return prefix + 'random_dir'
+
+
+def fake_parser_error(_, msg):
+ """Redirect parser.error() to exception."""
+ raise Exception(msg)
+
+
+def fake_generate_perf_report_exception(_):
+ raise Exception
+
+
+class HeatmapTest(unittest.TestCase):
+ """All of our tests for heat_map."""
+
+ #pylint: disable=protected-access
+ @mock.patch('shutil.copy2')
+ @mock.patch('tempfile.mkdtemp')
+ def test_EnsureFileInChrootAlreadyInside(self, mock_mkdtemp, mock_copy):
+ perf_data_inchroot = (
+ '/path/to/fake/chromeos_root/chroot/inchroot_path/perf.data')
+ heatmap = make_heatmap(perf_data=perf_data_inchroot)
+ heatmap._EnsureFileInChroot()
+ self.assertFalse(heatmap.temp_dir_created)
+ self.assertEqual(heatmap.temp_dir,
+ '/path/to/fake/chromeos_root/chroot/inchroot_path/')
+ self.assertEqual(heatmap.temp_perf_inchroot, '/inchroot_path/')
+ mock_mkdtemp.assert_not_called()
+ mock_copy.assert_not_called()
+
+ @mock.patch('shutil.copy2')
+ @mock.patch('tempfile.mkdtemp', fake_mkdtemp)
+ def test_EnsureFileInChrootOutsideNeedCopy(self, mock_copy):
+ heatmap = make_heatmap()
+ heatmap._EnsureFileInChroot()
+ self.assertTrue(heatmap.temp_dir_created)
+ self.assertEqual(mock_copy.call_count, 1)
+ self.assertEqual(heatmap.temp_dir,
+ '/path/to/fake/chromeos_root/src/random_dir')
+ self.assertEqual(heatmap.temp_perf_inchroot, '~/trunk/src/random_dir')
+
+ @mock.patch.object(command_executer.CommandExecuter, 'ChrootRunCommand')
+ def test_GeneratePerfReport(self, mock_ChrootRunCommand):
+ heatmap = make_heatmap()
+ heatmap.temp_dir = '/fake/chroot/inchroot_path/'
+ heatmap.temp_perf_inchroot = '/inchroot_path/'
+ mock_ChrootRunCommand.return_value = 0
+ heatmap._GeneratePerfReport()
+ cmd = ('cd %s && perf report -D -i perf.data > perf_report.txt' %
+ heatmap.temp_perf_inchroot)
+ mock_ChrootRunCommand.assert_called_with(heatmap.chromeos_root, cmd)
+ self.assertEqual(mock_ChrootRunCommand.call_count, 1)
+ self.assertEqual(heatmap.perf_report,
+ '/fake/chroot/inchroot_path/perf_report.txt')
+
+ @mock.patch('heatmap_generator.HeatmapGenerator')
+ def test_GetHeatMap(self, mock_heatmap_generator):
+ heatmap = make_heatmap()
+ heatmap._GetHeatMap(None)
+ self.assertTrue(mock_heatmap_generator.called)
+
+ @mock.patch.object(heat_map.HeatMapProducer, '_EnsureFileInChroot')
+ @mock.patch.object(heat_map.HeatMapProducer, '_GeneratePerfReport')
+ @mock.patch.object(heat_map.HeatMapProducer, '_GetHeatMap')
+ @mock.patch.object(heat_map.HeatMapProducer, '_RemoveFiles')
+ def test_Run(self, mock_remove_files, mock_get_heatmap,
+ mock_generate_perf_report, mock_ensure_file_in_chroot):
+ heatmap = make_heatmap()
+ heatmap.Run()
+ mock_ensure_file_in_chroot.assert_called_once_with()
+ mock_generate_perf_report.assert_called_once_with()
+ mock_get_heatmap.assert_called_once_with(None)
+ mock_remove_files.assert_called_once_with()
+
+ @mock.patch.object(heat_map.HeatMapProducer, '_EnsureFileInChroot')
+ @mock.patch.object(
+ heat_map.HeatMapProducer,
+ '_GeneratePerfReport',
+ new=fake_generate_perf_report_exception)
+ @mock.patch.object(heat_map.HeatMapProducer, '_GetHeatMap')
+ @mock.patch.object(heat_map.HeatMapProducer, '_RemoveFiles')
+ @mock.patch('__builtin__.print')
+ def test_Run_with_exception(self, mock_print, mock_remove_files,
+ mock_get_heatmap, mock_ensure_file_in_chroot):
+ heatmap = make_heatmap()
+ with self.assertRaises(Exception):
+ heatmap.Run()
+ mock_ensure_file_in_chroot.assert_called_once_with()
+ mock_get_heatmap.assert_not_called()
+ mock_remove_files.assert_called_once_with()
+ mock_print.assert_not_called()
+
+ @mock.patch('argparse.ArgumentParser.error', fake_parser_error)
+ @mock.patch.object(os.path, 'isfile')
+ @mock.patch.object(heat_map, 'IsARepoRoot')
+ def test_main_arg_format(self, mock_IsARepoRoot, mock_isfile):
+ """Test wrong arg format are detected."""
+ args = ['--chromeos_root=/fake/chroot/', '--perf_data=/path/to/perf.data']
+
+ # Test --chromeos_root format
+ mock_IsARepoRoot.return_value = False
+ with self.assertRaises(Exception) as msg:
+ heat_map.main(args)
+ self.assertIn('does not contain .repo dir.', str(msg.exception))
+
+ # Test --perf_data format
+ mock_IsARepoRoot.return_value = True
+ mock_isfile.return_value = False
+ with self.assertRaises(Exception) as msg:
+ heat_map.main(args)
+ self.assertIn('Cannot find perf_data', str(msg.exception))
+
+ # Test --hugepage format
+ mock_isfile.return_value = True
+ args.append('--hugepage=0')
+ with self.assertRaises(Exception) as msg:
+ heat_map.main(args)
+ self.assertIn('Wrong format of hugepage range', str(msg.exception))
+
+ # Test --hugepage parse
+ args[-1] = '--hugepage=0,4096'
+ heat_map.HeatMapProducer = mock.MagicMock()
+ heat_map.main(args)
+ heat_map.HeatMapProducer.assert_called_with(
+ '/fake/chroot/', '/path/to/perf.data', [0, 4096], None, '')
+
+
+if __name__ == '__main__':
+ unittest.main()