diff options
author | Tiancong Wang <tcwang@google.com> | 2019-05-06 15:42:43 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-05-17 18:38:15 -0700 |
commit | 3f06bf5fa1c53aa42959d351accc8888eb329343 (patch) | |
tree | 86be399d8cf24ff607f30a21f8b31634bffe4e4a /heatmaps/heat_map_test.py | |
parent | adb9f7a366cb5e8ae5eb5c860da191e0418e8901 (diff) | |
download | toolchain-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-x | heatmaps/heat_map_test.py | 157 |
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() |