| #!/usr/bin/env vpython3 |
| # Copyright 2021 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import os |
| import sys |
| import unittest |
| |
| sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir, 'perf')) |
| |
| from core import path_util |
| path_util.AddPyUtilsToPath() |
| path_util.AddTracingToPath() |
| |
| import metadata_extractor |
| from metadata_extractor import OSName |
| from core.tbmv3 import trace_processor |
| |
| import mock |
| |
| |
| class ExtractMetadataTestCase(unittest.TestCase): |
| def setUp(self): |
| self.trace_processor_path = 'trace_processor_shell' |
| self.trace_file = 'trace_file.proto' |
| |
| def _RunQueryParams(self, query): |
| """Returns tuple of RunQuery function parameters. |
| |
| Args: |
| query: sql query to extract metadata from proto trace. |
| """ |
| return (self.trace_processor_path, self.trace_file, query) |
| |
| def _CreateRunQueryResults(self, |
| version_number_results=frozenset([]), |
| os_name_results=frozenset([]), |
| architecture_results=frozenset([]), |
| bitness_results=frozenset([]), |
| version_code_results=frozenset([]), |
| modules_results=frozenset([])): |
| """Mock return of RunQuery calls. |
| |
| See trace_processor.RunQuery for the format of the query results. |
| Each parameter is a result dictionary for corresponding SQL query |
| defined in metadata_extractor.py. For example, valid value for |
| os_name_results = [{'str_value' : 'pineapple'}] |
| |
| Returns: |
| A dictionary mapping of RunQuery parameters to their mocked |
| RunQuery function return values. |
| """ |
| return { |
| self._RunQueryParams(metadata_extractor.VERSION_NUM_QUERY): |
| version_number_results, |
| self._RunQueryParams(metadata_extractor.OS_NAME_QUERY): os_name_results, |
| self._RunQueryParams(metadata_extractor.ARCH_QUERY): |
| architecture_results, |
| self._RunQueryParams(metadata_extractor.BITNESS_QUERY): bitness_results, |
| self._RunQueryParams(metadata_extractor.VERSION_CODE_QUERY): |
| version_code_results, |
| self._RunQueryParams(metadata_extractor.MODULES_QUERY): modules_results |
| } |
| |
| def _CreateRunQueryResultsFromValues(self, |
| version_number=None, |
| os_name=None, |
| architecture=None, |
| bitness=None, |
| version_code=None, |
| modules=None): |
| """Mock return of RunQuery calls by values, except for modules. |
| |
| Args: |
| version_number: string containing chrome version number |
| (eg: 'Chrome/93.0.4537.0'). |
| os_name: string of platform of the trace writer (eg. 'Android'). |
| architecture: string of OS arch of the trace writer, as returned by |
| base::SysInfo::OperatingSystemArchitecture() (eg: 'x86_64). |
| bitness: string of architecture bitness (eg. '32', '64'). |
| version_code: string of version code of chrome used by Android |
| play store. |
| modules: list of dictionaries mock return value of RunQuery |
| when its called with sql query metadata_extractor.MODULES_QUERY |
| See _CreateRunQueryResults function for more information. |
| (eg: [{'name': '/libmonochrome.so, 'build_id': '3284389AB83CD'}]). |
| |
| Returns: |
| A dictionary mapping of RunQuery parameters to their mocked |
| RunQuery function return values. |
| """ |
| return self._CreateRunQueryResults(version_number_results=[{ |
| 'str_value': |
| version_number |
| }], |
| os_name_results=[{ |
| 'str_value': os_name |
| }], |
| architecture_results=[{ |
| 'str_value': |
| architecture |
| }], |
| bitness_results=[{ |
| 'int_value': bitness |
| }], |
| version_code_results=[{ |
| 'int_value': |
| version_code |
| }], |
| modules_results=modules) |
| |
| def testExtractMetadata(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResultsFromValues( |
| version_number='Chrome/36.9.7934.4', |
| os_name='Android', |
| architecture='x86_64', |
| bitness='64', |
| version_code='857854', |
| modules=[{ |
| 'name': '/libmonochrome.so', |
| 'build_id': '3284389AB83CD' |
| }, { |
| 'name': '/missing', |
| 'build_id': 'AB3288CDE3283' |
| }, { |
| 'name': '/chrome.so', |
| 'build_id': 'abcdef' |
| }]) |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| extractor.Initialize() |
| |
| self.assertEqual(extractor.version_number, '36.9.7934.4') |
| self.assertEqual(extractor.os_name, OSName.ANDROID) |
| self.assertEqual(extractor.architecture, 'x86_64') |
| self.assertEqual(extractor.bitness, '64') |
| self.assertEqual(extractor.version_code, '857854') |
| self.assertEqual(extractor.modules, { |
| '/libmonochrome.so': '3284389AB83CD', |
| '/chrome.so': 'ABCDEF' |
| }) |
| |
| def testExtractMetadataEmptyList(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResults() |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| extractor.Initialize() |
| |
| self.assertEqual(extractor.version_number, None) |
| self.assertEqual(extractor.os_name, None) |
| self.assertEqual(extractor.architecture, None) |
| self.assertEqual(extractor.bitness, None) |
| self.assertEqual(extractor.version_code, None) |
| self.assertEqual(extractor.modules, None) |
| |
| def testExtractMetadataValuesNull(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResultsFromValues(modules=[{ |
| 'name': None, |
| 'build_id': None |
| }, { |
| 'name': None, |
| 'build_id': None |
| }]) |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| extractor.Initialize() |
| |
| self.assertEqual(extractor.version_number, None) |
| self.assertEqual(extractor.os_name, None) |
| self.assertEqual(extractor.architecture, None) |
| self.assertEqual(extractor.bitness, None) |
| self.assertEqual(extractor.version_code, None) |
| self.assertEqual(extractor.modules, None) |
| |
| def testExtractMetadataVersionNumberParsed(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResultsFromValues( |
| version_number='36.9.7934.4') |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| extractor.Initialize() |
| |
| self.assertEqual(extractor.version_number, '36.9.7934.4') |
| |
| def testParseOSNameAndroid(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResultsFromValues(os_name='Android') |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| extractor.Initialize() |
| |
| self.assertEqual(extractor.os_name, OSName.ANDROID) |
| |
| def testParseOSNameLinux(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResultsFromValues(os_name='Linux') |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| extractor.Initialize() |
| |
| self.assertEqual(extractor.os_name, OSName.LINUX) |
| |
| def testParseMac64(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResultsFromValues( |
| os_name='Mac OS X', version_number='Chrome/28.9.9364.32-64') |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| extractor.Initialize() |
| |
| self.assertEqual(extractor.version_number, '28.9.9364.32') |
| self.assertEqual(extractor.os_name, OSName.MAC) |
| |
| def testParseOSNameWindows(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResultsFromValues(os_name='Windows NT') |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| extractor.Initialize() |
| |
| self.assertEqual(extractor.os_name, OSName.WINDOWS) |
| |
| def testParseOSNameCrOS(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResultsFromValues(os_name='CrOS') |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| extractor.Initialize() |
| |
| self.assertEqual(extractor.os_name, OSName.CROS) |
| |
| def testParseOSNameFuschia(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResultsFromValues(os_name='Fuschia') |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| extractor.Initialize() |
| |
| self.assertEqual(extractor.os_name, OSName.FUSCHIA) |
| |
| def testParseOSNameNotRecognized(self): |
| def side_effect(*args): |
| params = self._CreateRunQueryResultsFromValues(os_name='blah') |
| return params[args] |
| |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| trace_processor.RunQuery = mock.MagicMock(side_effect=side_effect) |
| |
| exception_msg = 'OS name "blah" not recognized: ' + self.trace_file |
| with self.assertRaises(Exception) as context: |
| extractor.Initialize() |
| self.assertEqual(exception_msg, str(context.exception)) |
| |
| def testGetModuleIds(self): |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| extractor.InitializeForTesting(modules={ |
| 'name': '13423EDFAB2', |
| 'name2': '321468945', |
| 'name3': '4093492737482' |
| }) |
| self.assertEqual(extractor.GetModuleIds(), |
| {'13423EDFAB2', '321468945', '4093492737482'}) |
| |
| def testGetModuleIdsEmpty(self): |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| extractor.InitializeForTesting(modules={}) |
| self.assertEqual(extractor.GetModuleIds(), set()) |
| |
| def testGetModuleIdsNone(self): |
| extractor = metadata_extractor.MetadataExtractor(self.trace_processor_path, |
| self.trace_file) |
| extractor.InitializeForTesting(modules=None) |
| self.assertEqual(extractor.GetModuleIds(), None) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |