123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- #!/usr/bin/env vpython3
- # Copyright 2019 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- import copy
- import json
- import os
- import subprocess
- import sys
- import unittest
- import mock
- import merge_results
- import merge_steps
- import merge_lib as merger
- class MergeProfilesTest(unittest.TestCase):
- # pylint: disable=super-with-arguments
- def __init__(self, *args, **kwargs):
- super(MergeProfilesTest, self).__init__(*args, **kwargs)
- self.maxDiff = None
- # pylint: enable=super-with-arguments
- def test_merge_script_api_parameters(self):
- """Test the step-level merge front-end."""
- build_properties = json.dumps({
- 'some': {
- 'complicated': ['nested', {
- 'json': None,
- 'object': 'thing',
- }]
- }
- })
- task_output_dir = 'some/task/output/dir'
- profdata_dir = '/some/different/path/to/profdata/default.profdata'
- profdata_file = os.path.join(profdata_dir, 'base_unittests.profdata')
- args = [
- 'script_name', '--output-json', 'output.json', '--build-properties',
- build_properties, '--summary-json', 'summary.json', '--task-output-dir',
- task_output_dir, '--profdata-dir', profdata_dir, '--llvm-profdata',
- 'llvm-profdata', 'a.json', 'b.json', 'c.json', '--test-target-name',
- 'base_unittests', '--sparse'
- ]
- with mock.patch.object(merger, 'merge_profiles') as mock_merge:
- mock_merge.return_value = None, None
- with mock.patch.object(sys, 'argv', args):
- merge_results.main()
- self.assertEqual(
- mock_merge.call_args,
- mock.call(task_output_dir, profdata_file, '.profraw',
- 'llvm-profdata', sparse=True,
- skip_validation=False), None)
- def test_merge_steps_parameters(self):
- """Test the build-level merge front-end."""
- input_dir = 'some/task/output/dir'
- output_file = '/some/different/path/to/profdata/merged.profdata'
- args = [
- 'script_name',
- '--input-dir',
- input_dir,
- '--output-file',
- output_file,
- '--llvm-profdata',
- 'llvm-profdata',
- '--profdata-filename-pattern',
- '.*'
- ]
- with mock.patch.object(merger, 'merge_profiles') as mock_merge:
- mock_merge.return_value = None
- with mock.patch.object(sys, 'argv', args):
- merge_steps.main()
- self.assertEqual(
- mock_merge.call_args,
- mock.call(input_dir, output_file, '.profdata', 'llvm-profdata',
- '.*', sparse=False))
- @mock.patch.object(merger, '_validate_and_convert_profraws')
- def test_merge_profraw(self, mock_validate_and_convert_profraws):
- mock_input_dir_walk = [
- ('/b/some/path', ['0', '1', '2', '3'], ['summary.json']),
- ('/b/some/path/0', [],
- ['output.json', 'default-1.profraw', 'default-2.profraw']),
- ('/b/some/path/1', [],
- ['output.json', 'default-1.profraw', 'default-2.profraw']),
- ]
- mock_validate_and_convert_profraws.return_value = [
- '/b/some/path/0/default-1.profdata',
- '/b/some/path/1/default-2.profdata',
- ], [
- '/b/some/path/0/default-2.profraw',
- '/b/some/path/1/default-1.profraw',
- ], [
- '/b/some/path/1/default-1.profraw',
- ]
- with mock.patch.object(os, 'walk') as mock_walk:
- with mock.patch.object(os, 'remove'):
- mock_walk.return_value = mock_input_dir_walk
- with mock.patch.object(subprocess, 'check_call') as mock_exec_cmd:
- merger.merge_profiles('/b/some/path', 'output/dir/default.profdata',
- '.profraw', 'llvm-profdata')
- self.assertEqual(
- mock.call(
- [
- 'llvm-profdata',
- 'merge',
- '-o',
- 'output/dir/default.profdata',
- '/b/some/path/0/default-1.profdata',
- '/b/some/path/1/default-2.profdata',
- ],
- stderr=-2,
- ), mock_exec_cmd.call_args)
- self.assertTrue(mock_validate_and_convert_profraws.called)
- @mock.patch.object(merger, '_validate_and_convert_profraws')
- def test_profraw_skip_validation(self, mock_validate_and_convert_profraws):
- mock_input_dir_walk = [
- ('/b/some/path', ['0', '1', '2', '3'], ['summary.json']),
- ('/b/some/path/0', [],
- ['output.json', 'default-1.profraw', 'default-2.profraw']),
- ('/b/some/path/1', [],
- ['output.json', 'default-1.profraw', 'default-2.profraw']),
- ]
- with mock.patch.object(os, 'walk') as mock_walk:
- with mock.patch.object(os, 'remove'):
- mock_walk.return_value = mock_input_dir_walk
- with mock.patch.object(subprocess, 'check_call') as mock_exec_cmd:
- merger.merge_profiles('/b/some/path',
- 'output/dir/default.profdata',
- '.profraw',
- 'llvm-profdata',
- skip_validation=True)
- self.assertEqual(
- mock.call(
- [
- 'llvm-profdata',
- 'merge',
- '-o',
- 'output/dir/default.profdata',
- '/b/some/path/0/default-1.profraw',
- '/b/some/path/0/default-2.profraw',
- '/b/some/path/1/default-1.profraw',
- '/b/some/path/1/default-2.profraw'
- ],
- stderr=-2,
- ), mock_exec_cmd.call_args)
- # Skip validation should've passed all profraw files directly, and
- # this validate call should not have been invoked.
- self.assertFalse(mock_validate_and_convert_profraws.called)
- def test_merge_profraw_skip_if_there_is_no_file(self):
- mock_input_dir_walk = [
- ('/b/some/path', ['0', '1', '2', '3'], ['summary.json']),
- ]
- with mock.patch.object(os, 'walk') as mock_walk:
- mock_walk.return_value = mock_input_dir_walk
- with mock.patch.object(subprocess, 'check_call') as mock_exec_cmd:
- merger.merge_profiles('/b/some/path', 'output/dir/default.profdata',
- '.profraw', 'llvm-profdata')
- self.assertFalse(mock_exec_cmd.called)
- @mock.patch.object(merger, '_validate_and_convert_profraws')
- def test_merge_profdata(self, mock_validate_and_convert_profraws):
- mock_input_dir_walk = [
- ('/b/some/path', ['base_unittests', 'url_unittests'], ['summary.json']),
- ('/b/some/path/base_unittests', [], ['output.json',
- 'default.profdata']),
- ('/b/some/path/url_unittests', [], ['output.json', 'default.profdata']),
- ]
- with mock.patch.object(os, 'walk') as mock_walk:
- with mock.patch.object(os, 'remove'):
- mock_walk.return_value = mock_input_dir_walk
- with mock.patch.object(subprocess, 'check_call') as mock_exec_cmd:
- merger.merge_profiles('/b/some/path', 'output/dir/default.profdata',
- '.profdata', 'llvm-profdata')
- self.assertEqual(
- mock.call(
- [
- 'llvm-profdata',
- 'merge',
- '-o',
- 'output/dir/default.profdata',
- '/b/some/path/base_unittests/default.profdata',
- '/b/some/path/url_unittests/default.profdata',
- ],
- stderr=-2,
- ), mock_exec_cmd.call_args)
- # The mock method should only apply when merging .profraw files.
- self.assertFalse(mock_validate_and_convert_profraws.called)
- @mock.patch.object(merger, '_validate_and_convert_profraws')
- def test_merge_profdata_pattern(self, mock_validate_and_convert_profraws):
- mock_input_dir_walk = [
- ('/b/some/path', ['base_unittests', 'url_unittests'], ['summary.json']),
- ('/b/some/path/base_unittests', [], ['output.json',
- 'base_unittests.profdata']),
- ('/b/some/path/url_unittests', [], ['output.json',
- 'url_unittests.profdata'],),
- ('/b/some/path/ios_chrome_smoke_eg2tests',
- [], ['output.json','ios_chrome_smoke_eg2tests.profdata'],),
- ]
- with mock.patch.object(os, 'walk') as mock_walk:
- with mock.patch.object(os, 'remove'):
- mock_walk.return_value = mock_input_dir_walk
- with mock.patch.object(subprocess, 'check_call') as mock_exec_cmd:
- input_profdata_filename_pattern = '.+_unittests\.profdata'
- merger.merge_profiles('/b/some/path',
- 'output/dir/default.profdata',
- '.profdata',
- 'llvm-profdata',
- input_profdata_filename_pattern)
- self.assertEqual(
- mock.call(
- [
- 'llvm-profdata',
- 'merge',
- '-o',
- 'output/dir/default.profdata',
- '/b/some/path/base_unittests/base_unittests.profdata',
- '/b/some/path/url_unittests/url_unittests.profdata',
- ],
- stderr=-2,
- ), mock_exec_cmd.call_args)
- # The mock method should only apply when merging .profraw files.
- self.assertFalse(mock_validate_and_convert_profraws.called)
- @mock.patch('merge_lib._JAVA_PATH', 'java')
- def test_merge_java_exec_files(self):
- mock_input_dir_walk = [
- ('/b/some/path', ['0', '1', '2', '3'], ['summary.json']),
- ('/b/some/path/0', [],
- ['output.json', 'default-1.exec', 'default-2.exec']),
- ('/b/some/path/1', [],
- ['output.json', 'default-3.exec', 'default-4.exec']),
- ]
- with mock.patch.object(os, 'walk') as mock_walk:
- mock_walk.return_value = mock_input_dir_walk
- with mock.patch.object(subprocess, 'check_call') as mock_exec_cmd:
- merger.merge_java_exec_files(
- '/b/some/path', 'output/path', 'path/to/jacococli.jar')
- self.assertEqual(
- mock.call(
- [
- 'java',
- '-jar',
- 'path/to/jacococli.jar',
- 'merge',
- '/b/some/path/0/default-1.exec',
- '/b/some/path/0/default-2.exec',
- '/b/some/path/1/default-3.exec',
- '/b/some/path/1/default-4.exec',
- '--destfile',
- 'output/path',
- ],
- stderr=-2,
- ), mock_exec_cmd.call_args)
- def test_merge_java_exec_files_if_there_is_no_file(self):
- mock_input_dir_walk = [
- ('/b/some/path', ['0', '1', '2', '3'], ['summary.json']),
- ]
- with mock.patch.object(os, 'walk') as mock_walk:
- mock_walk.return_value = mock_input_dir_walk
- with mock.patch.object(subprocess, 'check_call') as mock_exec_cmd:
- merger.merge_java_exec_files(
- '/b/some/path', 'output/path', 'path/to/jacococli.jar')
- self.assertFalse(mock_exec_cmd.called)
- def test_calls_merge_js_results_script(self):
- task_output_dir = 'some/task/output/dir'
- profdata_dir = '/some/different/path/to/profdata/default.profdata'
- args = [
- 'script_name', '--output-json', 'output.json', '--task-output-dir',
- task_output_dir, '--profdata-dir', profdata_dir, '--llvm-profdata',
- 'llvm-profdata', 'a.json', 'b.json', 'c.json', '--test-target-name',
- 'v8_unittests', '--sparse',
- '--javascript-coverage-dir', 'output/dir/devtools_code_coverage',
- '--merged-js-cov-filename', 'path/js/cov/filename'
- ]
- with mock.patch.object(merger, 'merge_profiles') as mock_merge:
- mock_merge.return_value = None, None
- with mock.patch.object(sys, 'argv', args):
- with mock.patch.object(subprocess, 'call') as mock_exec_cmd:
- with mock.patch.object(os.path, 'join') as mock_os_path_join:
- mock_merge_js_results_path = 'path/to/js/merge_js_results.py'
- mock_os_path_join.return_value = mock_merge_js_results_path
- python_exec = sys.executable
- merge_results.main()
- mock_exec_cmd.assert_called_with(
- [python_exec, mock_merge_js_results_path, '--task-output-dir',
- task_output_dir, '--javascript-coverage-dir',
- 'output/dir/devtools_code_coverage',
- '--merged-js-cov-filename', 'path/js/cov/filename'])
- def test_argparse_sparse(self):
- """Ensure that sparse flag defaults to true, and is set to correct value"""
- # Basic required args
- build_properties = json.dumps({
- 'some': {
- 'complicated': ['nested', {
- 'json': None,
- 'object': 'thing',
- }]
- }
- })
- task_output_dir = 'some/task/output/dir'
- profdata_dir = '/some/different/path/to/profdata/default.profdata'
- profdata_file = os.path.join(profdata_dir, 'base_unittests.profdata')
- args = [
- 'script_name', '--output-json', 'output.json', '--build-properties',
- build_properties, '--summary-json', 'summary.json', '--task-output-dir',
- task_output_dir, '--profdata-dir', profdata_dir, '--llvm-profdata',
- 'llvm-profdata', 'a.json', 'b.json', 'c.json', '--test-target-name',
- 'base_unittests'
- ]
- test_scenarios = [
- {
- # Base set of args should set --sparse to false by default
- 'args': None,
- 'expected_outcome': False,
- },
- {
- # Sparse should parse True when only --sparse is specified
- 'args': ['--sparse'],
- 'expected_outcome': True,
- }
- ]
- for scenario in test_scenarios:
- args = copy.deepcopy(args)
- additional_args = scenario['args']
- if additional_args:
- args.extend(additional_args)
- expected_outcome = scenario['expected_outcome']
- with mock.patch.object(merger, 'merge_profiles') as mock_merge:
- mock_merge.return_value = None, None
- with mock.patch.object(sys, 'argv', args):
- merge_results.main()
- self.assertEqual(
- mock_merge.call_args,
- mock.call(task_output_dir, profdata_file, '.profraw',
- 'llvm-profdata', sparse=expected_outcome,
- skip_validation=False), None)
- if __name__ == '__main__':
- unittest.main()
|