1# 2# Copyright (C) 2024 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17import builtins 18import unittest 19import sys 20import os 21import subprocess 22from unittest import mock 23from src.torq import create_parser, verify_args 24 25TORQ_TEMP_DIR = "/tmp/.torq" 26ANDROID_BUILD_TOP = "/folder" 27ANDROID_PRODUCT_OUT = "/folder/out/product/seahawk" 28SYMBOLS_PATH = "/folder/symbols" 29 30 31class ValidateSimpleperfUnitTest(unittest.TestCase): 32 33 def set_up_parser(self, command_string): 34 sys.argv = command_string.split() 35 return create_parser() 36 37 @mock.patch.object(os.path, "exists", autospec=True) 38 @mock.patch.object(os.path, "isdir", autospec=True) 39 @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP, 40 "ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, 41 clear=True) 42 def test_create_parser_valid_symbols(self, mock_isdir, mock_exists): 43 mock_isdir.return_value = True 44 mock_exists.return_value = True 45 parser = self.set_up_parser("torq.py -p simpleperf " 46 "--symbols %s" % SYMBOLS_PATH) 47 48 args = parser.parse_args() 49 args, error = verify_args(args) 50 51 self.assertEqual(error, None) 52 self.assertEqual(args.symbols, SYMBOLS_PATH) 53 self.assertEqual(args.scripts_path, "%s/system/extras/simpleperf/scripts" 54 % ANDROID_BUILD_TOP) 55 56 @mock.patch.object(os.path, "exists", autospec=True) 57 @mock.patch.object(os.path, "isdir", autospec=True) 58 @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP, 59 "ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, 60 clear=True) 61 def test_create_parser_valid_android_product_out_no_symbols(self, 62 mock_isdir, mock_exists): 63 mock_isdir.return_value = True 64 mock_exists.return_value = True 65 parser = self.set_up_parser("torq.py -p simpleperf") 66 67 args = parser.parse_args() 68 args, error = verify_args(args) 69 70 self.assertEqual(error, None) 71 self.assertEqual(args.symbols, ANDROID_PRODUCT_OUT) 72 self.assertEqual(args.scripts_path, "%s/system/extras/simpleperf/scripts" 73 % ANDROID_BUILD_TOP) 74 75 @mock.patch.dict(os.environ, {"ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, 76 clear=True) 77 @mock.patch.object(os.path, "exists", autospec=True) 78 @mock.patch.object(os.path, "isdir", autospec=True) 79 def test_create_parser_invalid_android_product_no_symbols(self, 80 mock_isdir, mock_exists): 81 mock_isdir.return_value = False 82 mock_exists.return_value = False 83 parser = self.set_up_parser("torq.py -p simpleperf") 84 85 args = parser.parse_args() 86 args, error = verify_args(args) 87 88 self.assertEqual(error.message, ("%s is not a valid $ANDROID_PRODUCT_OUT." 89 % ANDROID_PRODUCT_OUT)) 90 self.assertEqual(error.suggestion, "Set --symbols to a valid symbols lib " 91 "path or set $ANDROID_PRODUCT_OUT to " 92 "your android product out directory " 93 "(<ANDROID_BUILD_TOP>/out/target/product" 94 "/<TARGET>).") 95 96 @mock.patch.dict(os.environ, {}, 97 clear=True) 98 @mock.patch.object(os.path, "exists", autospec=True) 99 @mock.patch.object(os.path, "isdir", autospec=True) 100 def test_create_parser_invalid_symbols_no_android_product_out(self, 101 mock_isdir, mock_exists): 102 mock_isdir.return_value = False 103 mock_exists.return_value = False 104 parser = self.set_up_parser("torq.py -p simpleperf " 105 "--symbols %s" % SYMBOLS_PATH) 106 107 args = parser.parse_args() 108 args, error = verify_args(args) 109 110 self.assertEqual(error.message, ("%s is not a valid path." % SYMBOLS_PATH)) 111 self.assertEqual(error.suggestion, "Set --symbols to a valid symbols lib " 112 "path or set $ANDROID_PRODUCT_OUT to " 113 "your android product out directory " 114 "(<ANDROID_BUILD_TOP>/out/target/product" 115 "/<TARGET>).") 116 117 @mock.patch.dict(os.environ, {}, clear=True) 118 @mock.patch.object(os.path, "exists", autospec=True) 119 @mock.patch.object(os.path, "isdir", autospec=True) 120 def test_create_parser_no_android_product_out_no_symbols(self, mock_isdir, 121 mock_exists): 122 mock_isdir.return_value = False 123 mock_exists.return_value = False 124 parser = self.set_up_parser("torq.py -p simpleperf") 125 126 args = parser.parse_args() 127 args, error = verify_args(args) 128 129 self.assertEqual(error.message, "ANDROID_PRODUCT_OUT is not set.") 130 self.assertEqual(error.suggestion, "Set --symbols to a valid symbols lib " 131 "path or set $ANDROID_PRODUCT_OUT to " 132 "your android product out directory " 133 "(<ANDROID_BUILD_TOP>/out/target/" 134 "product/<TARGET>).") 135 136 @mock.patch.dict(os.environ, {"ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, 137 clear=True) 138 @mock.patch.object(os.path, "exists", autospec=True) 139 @mock.patch.object(os.path, "isdir", autospec=True) 140 @mock.patch.object(subprocess, "run", autospec=True) 141 @mock.patch.object(builtins, "input") 142 def test_create_parser_successfully_download_scripts(self, mock_input, 143 mock_subprocess_run, mock_isdir, mock_exists): 144 mock_isdir.return_value = True 145 mock_input.return_value = "y" 146 mock_exists.side_effect = [False, True] 147 mock_subprocess_run.return_value = None 148 parser = self.set_up_parser("torq.py -p simpleperf") 149 150 args = parser.parse_args() 151 args, error = verify_args(args) 152 153 self.assertEqual(error, None) 154 self.assertEqual(args.symbols, ANDROID_PRODUCT_OUT) 155 self.assertEqual(args.scripts_path, TORQ_TEMP_DIR) 156 157 @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP}, 158 clear=True) 159 @mock.patch.object(os.path, "exists", autospec=True) 160 @mock.patch.object(os.path, "isdir", autospec=True) 161 @mock.patch.object(subprocess, "run", autospec=True) 162 @mock.patch.object(builtins, "input") 163 def test_create_parser_failed_to_download_scripts(self, mock_input, 164 mock_subprocess_run, mock_isdir, mock_exists): 165 mock_isdir.return_value = True 166 mock_input.return_value = "y" 167 mock_exists.side_effect = [False, False, False] 168 mock_subprocess_run.return_value = None 169 parser = self.set_up_parser("torq.py -p simpleperf --symbols %s" 170 % SYMBOLS_PATH) 171 172 args = parser.parse_args() 173 with self.assertRaises(Exception) as e: 174 args, error = verify_args(args) 175 176 self.assertEqual(str(e.exception), 177 "Error while downloading simpleperf scripts. Try " 178 "again or set $ANDROID_BUILD_TOP to your android root " 179 "path and make sure you have $ANDROID_BUILD_TOP/system" 180 "/extras/simpleperf/scripts downloaded.") 181 182 @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP}, 183 clear=True) 184 @mock.patch.object(os.path, "exists", autospec=True) 185 @mock.patch.object(os.path, "isdir", autospec=True) 186 @mock.patch.object(builtins, "input") 187 def test_create_parser_download_scripts_wrong_input(self, mock_input, 188 mock_isdir, mock_exists): 189 mock_isdir.return_value = True 190 mock_input.return_value = "bad-input" 191 mock_exists.side_effect = [False, False] 192 parser = self.set_up_parser("torq.py -p simpleperf --symbols %s" 193 % SYMBOLS_PATH) 194 195 args = parser.parse_args() 196 args, error = verify_args(args) 197 198 self.assertEqual(error.message, "Invalid inputs.") 199 self.assertEqual(error.suggestion, "Set $ANDROID_BUILD_TOP to your android " 200 "root path and make sure you have " 201 "$ANDROID_BUILD_TOP/system/extras/" 202 "simpleperf/scripts downloaded.") 203 204 @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP}, 205 clear=True) 206 @mock.patch.object(os.path, "exists", autospec=True) 207 @mock.patch.object(os.path, "isdir", autospec=True) 208 @mock.patch.object(builtins, "input") 209 def test_create_parser_download_scripts_refuse_download(self, mock_input, 210 mock_isdir, mock_exists): 211 mock_isdir.return_value = True 212 mock_input.return_value = "n" 213 mock_exists.side_effect = [False, False] 214 parser = self.set_up_parser("torq.py -p simpleperf --symbols %s" 215 % SYMBOLS_PATH) 216 217 args = parser.parse_args() 218 args, error = verify_args(args) 219 220 self.assertEqual(error.message, "Did not download simpleperf scripts.") 221 self.assertEqual(error.suggestion, "Set $ANDROID_BUILD_TOP to your android " 222 "root path and make sure you have " 223 "$ANDROID_BUILD_TOP/system/extras/" 224 "simpleperf/scripts downloaded.") 225 226 227if __name__ == '__main__': 228 unittest.main() 229