| # | |
| # Copyright (C) 2024 The Android Open Source Project | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| # | |
| import builtins | |
| import unittest | |
| import sys | |
| import os | |
| import subprocess | |
| from unittest import mock | |
| from torq import create_parser, verify_args | |
| TORQ_TEMP_DIR = "/tmp/.torq" | |
| ANDROID_BUILD_TOP = "/folder" | |
| ANDROID_PRODUCT_OUT = "/folder/out/product/seahawk" | |
| SYMBOLS_PATH = "/folder/symbols" | |
| class ValidateSimpleperfUnitTest(unittest.TestCase): | |
| def set_up_parser(self, command_string): | |
| parser = create_parser() | |
| sys.argv = command_string.split() | |
| return parser | |
| @mock.patch.object(os.path, "exists", autospec=True) | |
| @mock.patch.object(os.path, "isdir", autospec=True) | |
| @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP, | |
| "ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, | |
| clear=True) | |
| def test_create_parser_valid_symbols(self, mock_isdir, mock_exists): | |
| mock_isdir.return_value = True | |
| mock_exists.return_value = True | |
| parser = self.set_up_parser("torq.py -p simpleperf " | |
| "--symbols %s" % SYMBOLS_PATH) | |
| args = parser.parse_args() | |
| args, error = verify_args(args) | |
| self.assertEqual(error, None) | |
| self.assertEqual(args.symbols, SYMBOLS_PATH) | |
| self.assertEqual(args.scripts_path, "%s/system/extras/simpleperf/scripts" | |
| % ANDROID_BUILD_TOP) | |
| @mock.patch.object(os.path, "exists", autospec=True) | |
| @mock.patch.object(os.path, "isdir", autospec=True) | |
| @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP, | |
| "ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, | |
| clear=True) | |
| def test_create_parser_valid_android_product_out_no_symbols(self, | |
| mock_isdir, mock_exists): | |
| mock_isdir.return_value = True | |
| mock_exists.return_value = True | |
| parser = self.set_up_parser("torq.py -p simpleperf") | |
| args = parser.parse_args() | |
| args, error = verify_args(args) | |
| self.assertEqual(error, None) | |
| self.assertEqual(args.symbols, ANDROID_PRODUCT_OUT) | |
| self.assertEqual(args.scripts_path, "%s/system/extras/simpleperf/scripts" | |
| % ANDROID_BUILD_TOP) | |
| @mock.patch.dict(os.environ, {"ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, | |
| clear=True) | |
| @mock.patch.object(os.path, "exists", autospec=True) | |
| @mock.patch.object(os.path, "isdir", autospec=True) | |
| def test_create_parser_invalid_android_product_no_symbols(self, | |
| mock_isdir, mock_exists): | |
| mock_isdir.return_value = False | |
| mock_exists.return_value = False | |
| parser = self.set_up_parser("torq.py -p simpleperf") | |
| args = parser.parse_args() | |
| args, error = verify_args(args) | |
| self.assertEqual(error.message, ("%s is not a valid $ANDROID_PRODUCT_OUT." | |
| % ANDROID_PRODUCT_OUT)) | |
| self.assertEqual(error.suggestion, "Set --symbols to a valid symbols lib " | |
| "path or set $ANDROID_PRODUCT_OUT to " | |
| "your android product out directory " | |
| "(<ANDROID_BUILD_TOP>/out/target/product" | |
| "/<TARGET>).") | |
| @mock.patch.dict(os.environ, {}, | |
| clear=True) | |
| @mock.patch.object(os.path, "exists", autospec=True) | |
| @mock.patch.object(os.path, "isdir", autospec=True) | |
| def test_create_parser_invalid_symbols_no_android_product_out(self, | |
| mock_isdir, mock_exists): | |
| mock_isdir.return_value = False | |
| mock_exists.return_value = False | |
| parser = self.set_up_parser("torq.py -p simpleperf " | |
| "--symbols %s" % SYMBOLS_PATH) | |
| args = parser.parse_args() | |
| args, error = verify_args(args) | |
| self.assertEqual(error.message, ("%s is not a valid path." % SYMBOLS_PATH)) | |
| self.assertEqual(error.suggestion, "Set --symbols to a valid symbols lib " | |
| "path or set $ANDROID_PRODUCT_OUT to " | |
| "your android product out directory " | |
| "(<ANDROID_BUILD_TOP>/out/target/product" | |
| "/<TARGET>).") | |
| @mock.patch.dict(os.environ, {}, clear=True) | |
| @mock.patch.object(os.path, "exists", autospec=True) | |
| @mock.patch.object(os.path, "isdir", autospec=True) | |
| def test_create_parser_no_android_product_out_no_symbols(self, mock_isdir, | |
| mock_exists): | |
| mock_isdir.return_value = False | |
| mock_exists.return_value = False | |
| parser = self.set_up_parser("torq.py -p simpleperf") | |
| args = parser.parse_args() | |
| args, error = verify_args(args) | |
| self.assertEqual(error.message, "ANDROID_PRODUCT_OUT is not set.") | |
| self.assertEqual(error.suggestion, "Set --symbols to a valid symbols lib " | |
| "path or set $ANDROID_PRODUCT_OUT to " | |
| "your android product out directory " | |
| "(<ANDROID_BUILD_TOP>/out/target/" | |
| "product/<TARGET>).") | |
| @mock.patch.dict(os.environ, {"ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, | |
| clear=True) | |
| @mock.patch.object(os.path, "exists", autospec=True) | |
| @mock.patch.object(os.path, "isdir", autospec=True) | |
| @mock.patch.object(subprocess, "run", autospec=True) | |
| @mock.patch.object(builtins, "input") | |
| def test_create_parser_successfully_download_scripts(self, mock_input, | |
| mock_subprocess_run, mock_isdir, mock_exists): | |
| mock_isdir.return_value = True | |
| mock_input.return_value = "y" | |
| mock_exists.side_effect = [False, True] | |
| mock_subprocess_run.return_value = None | |
| parser = self.set_up_parser("torq.py -p simpleperf") | |
| args = parser.parse_args() | |
| args, error = verify_args(args) | |
| self.assertEqual(error, None) | |
| self.assertEqual(args.symbols, ANDROID_PRODUCT_OUT) | |
| self.assertEqual(args.scripts_path, TORQ_TEMP_DIR) | |
| @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP}, | |
| clear=True) | |
| @mock.patch.object(os.path, "exists", autospec=True) | |
| @mock.patch.object(os.path, "isdir", autospec=True) | |
| @mock.patch.object(subprocess, "run", autospec=True) | |
| @mock.patch.object(builtins, "input") | |
| def test_create_parser_failed_to_download_scripts(self, mock_input, | |
| mock_subprocess_run, mock_isdir, mock_exists): | |
| mock_isdir.return_value = True | |
| mock_input.return_value = "y" | |
| mock_exists.side_effect = [False, False, False] | |
| mock_subprocess_run.return_value = None | |
| parser = self.set_up_parser("torq.py -p simpleperf --symbols %s" | |
| % SYMBOLS_PATH) | |
| args = parser.parse_args() | |
| with self.assertRaises(Exception) as e: | |
| args, error = verify_args(args) | |
| self.assertEqual(str(e.exception), | |
| "Error while downloading simpleperf scripts. Try " | |
| "again or set $ANDROID_BUILD_TOP to your android root " | |
| "path and make sure you have $ANDROID_BUILD_TOP/system" | |
| "/extras/simpleperf/scripts downloaded.") | |
| @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP}, | |
| clear=True) | |
| @mock.patch.object(os.path, "exists", autospec=True) | |
| @mock.patch.object(os.path, "isdir", autospec=True) | |
| @mock.patch.object(builtins, "input") | |
| def test_create_parser_download_scripts_wrong_input(self, mock_input, | |
| mock_isdir, mock_exists): | |
| mock_isdir.return_value = True | |
| mock_input.return_value = "bad-input" | |
| mock_exists.side_effect = [False, False] | |
| parser = self.set_up_parser("torq.py -p simpleperf --symbols %s" | |
| % SYMBOLS_PATH) | |
| args = parser.parse_args() | |
| args, error = verify_args(args) | |
| self.assertEqual(error.message, "Invalid inputs.") | |
| self.assertEqual(error.suggestion, "Set $ANDROID_BUILD_TOP to your android " | |
| "root path and make sure you have " | |
| "$ANDROID_BUILD_TOP/system/extras/" | |
| "simpleperf/scripts downloaded.") | |
| @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP}, | |
| clear=True) | |
| @mock.patch.object(os.path, "exists", autospec=True) | |
| @mock.patch.object(os.path, "isdir", autospec=True) | |
| @mock.patch.object(builtins, "input") | |
| def test_create_parser_download_scripts_refuse_download(self, mock_input, | |
| mock_isdir, mock_exists): | |
| mock_isdir.return_value = True | |
| mock_input.return_value = "n" | |
| mock_exists.side_effect = [False, False] | |
| parser = self.set_up_parser("torq.py -p simpleperf --symbols %s" | |
| % SYMBOLS_PATH) | |
| args = parser.parse_args() | |
| args, error = verify_args(args) | |
| self.assertEqual(error.message, "Did not download simpleperf scripts.") | |
| self.assertEqual(error.suggestion, "Set $ANDROID_BUILD_TOP to your android " | |
| "root path and make sure you have " | |
| "$ANDROID_BUILD_TOP/system/extras/" | |
| "simpleperf/scripts downloaded.") | |
| if __name__ == '__main__': | |
| unittest.main() |