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 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 parser = create_parser() 35 sys.argv = command_string.split() 36 return parser 37 38 @mock.patch.object(os.path, "exists", autospec=True) 39 @mock.patch.object(os.path, "isdir", autospec=True) 40 @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP, 41 "ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, 42 clear=True) 43 def test_create_parser_valid_symbols(self, mock_isdir, mock_exists): 44 mock_isdir.return_value = True 45 mock_exists.return_value = True 46 parser = self.set_up_parser("torq.py -p simpleperf " 47 "--symbols %s" % SYMBOLS_PATH) 48 49 args = parser.parse_args() 50 args, error = verify_args(args) 51 52 self.assertEqual(error, None) 53 self.assertEqual(args.symbols, SYMBOLS_PATH) 54 self.assertEqual(args.scripts_path, "%s/system/extras/simpleperf/scripts" 55 % ANDROID_BUILD_TOP) 56 57 @mock.patch.object(os.path, "exists", autospec=True) 58 @mock.patch.object(os.path, "isdir", autospec=True) 59 @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP, 60 "ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, 61 clear=True) 62 def test_create_parser_valid_android_product_out_no_symbols(self, 63 mock_isdir, mock_exists): 64 mock_isdir.return_value = True 65 mock_exists.return_value = True 66 parser = self.set_up_parser("torq.py -p simpleperf") 67 68 args = parser.parse_args() 69 args, error = verify_args(args) 70 71 self.assertEqual(error, None) 72 self.assertEqual(args.symbols, ANDROID_PRODUCT_OUT) 73 self.assertEqual(args.scripts_path, "%s/system/extras/simpleperf/scripts" 74 % ANDROID_BUILD_TOP) 75 76 @mock.patch.dict(os.environ, {"ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, 77 clear=True) 78 @mock.patch.object(os.path, "exists", autospec=True) 79 @mock.patch.object(os.path, "isdir", autospec=True) 80 def test_create_parser_invalid_android_product_no_symbols(self, 81 mock_isdir, mock_exists): 82 mock_isdir.return_value = False 83 mock_exists.return_value = False 84 parser = self.set_up_parser("torq.py -p simpleperf") 85 86 args = parser.parse_args() 87 args, error = verify_args(args) 88 89 self.assertEqual(error.message, ("%s is not a valid $ANDROID_PRODUCT_OUT." 90 % ANDROID_PRODUCT_OUT)) 91 self.assertEqual(error.suggestion, "Set --symbols to a valid symbols lib " 92 "path or set $ANDROID_PRODUCT_OUT to " 93 "your android product out directory " 94 "(<ANDROID_BUILD_TOP>/out/target/product" 95 "/<TARGET>).") 96 97 @mock.patch.dict(os.environ, {}, 98 clear=True) 99 @mock.patch.object(os.path, "exists", autospec=True) 100 @mock.patch.object(os.path, "isdir", autospec=True) 101 def test_create_parser_invalid_symbols_no_android_product_out(self, 102 mock_isdir, mock_exists): 103 mock_isdir.return_value = False 104 mock_exists.return_value = False 105 parser = self.set_up_parser("torq.py -p simpleperf " 106 "--symbols %s" % SYMBOLS_PATH) 107 108 args = parser.parse_args() 109 args, error = verify_args(args) 110 111 self.assertEqual(error.message, ("%s is not a valid path." % SYMBOLS_PATH)) 112 self.assertEqual(error.suggestion, "Set --symbols to a valid symbols lib " 113 "path or set $ANDROID_PRODUCT_OUT to " 114 "your android product out directory " 115 "(<ANDROID_BUILD_TOP>/out/target/product" 116 "/<TARGET>).") 117 118 @mock.patch.dict(os.environ, {}, clear=True) 119 @mock.patch.object(os.path, "exists", autospec=True) 120 @mock.patch.object(os.path, "isdir", autospec=True) 121 def test_create_parser_no_android_product_out_no_symbols(self, mock_isdir, 122 mock_exists): 123 mock_isdir.return_value = False 124 mock_exists.return_value = False 125 parser = self.set_up_parser("torq.py -p simpleperf") 126 127 args = parser.parse_args() 128 args, error = verify_args(args) 129 130 self.assertEqual(error.message, "ANDROID_PRODUCT_OUT is not set.") 131 self.assertEqual(error.suggestion, "Set --symbols to a valid symbols lib " 132 "path or set $ANDROID_PRODUCT_OUT to " 133 "your android product out directory " 134 "(<ANDROID_BUILD_TOP>/out/target/" 135 "product/<TARGET>).") 136 137 @mock.patch.dict(os.environ, {"ANDROID_PRODUCT_OUT": ANDROID_PRODUCT_OUT}, 138 clear=True) 139 @mock.patch.object(os.path, "exists", autospec=True) 140 @mock.patch.object(os.path, "isdir", autospec=True) 141 @mock.patch.object(subprocess, "run", autospec=True) 142 @mock.patch.object(builtins, "input") 143 def test_create_parser_successfully_download_scripts(self, mock_input, 144 mock_subprocess_run, mock_isdir, mock_exists): 145 mock_isdir.return_value = True 146 mock_input.return_value = "y" 147 mock_exists.side_effect = [False, True] 148 mock_subprocess_run.return_value = None 149 parser = self.set_up_parser("torq.py -p simpleperf") 150 151 args = parser.parse_args() 152 args, error = verify_args(args) 153 154 self.assertEqual(error, None) 155 self.assertEqual(args.symbols, ANDROID_PRODUCT_OUT) 156 self.assertEqual(args.scripts_path, TORQ_TEMP_DIR) 157 158 @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP}, 159 clear=True) 160 @mock.patch.object(os.path, "exists", autospec=True) 161 @mock.patch.object(os.path, "isdir", autospec=True) 162 @mock.patch.object(subprocess, "run", autospec=True) 163 @mock.patch.object(builtins, "input") 164 def test_create_parser_failed_to_download_scripts(self, mock_input, 165 mock_subprocess_run, mock_isdir, mock_exists): 166 mock_isdir.return_value = True 167 mock_input.return_value = "y" 168 mock_exists.side_effect = [False, False, False] 169 mock_subprocess_run.return_value = None 170 parser = self.set_up_parser("torq.py -p simpleperf --symbols %s" 171 % SYMBOLS_PATH) 172 173 args = parser.parse_args() 174 with self.assertRaises(Exception) as e: 175 args, error = verify_args(args) 176 177 self.assertEqual(str(e.exception), 178 "Error while downloading simpleperf scripts. Try " 179 "again or set $ANDROID_BUILD_TOP to your android root " 180 "path and make sure you have $ANDROID_BUILD_TOP/system" 181 "/extras/simpleperf/scripts downloaded.") 182 183 @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP}, 184 clear=True) 185 @mock.patch.object(os.path, "exists", autospec=True) 186 @mock.patch.object(os.path, "isdir", autospec=True) 187 @mock.patch.object(builtins, "input") 188 def test_create_parser_download_scripts_wrong_input(self, mock_input, 189 mock_isdir, mock_exists): 190 mock_isdir.return_value = True 191 mock_input.return_value = "bad-input" 192 mock_exists.side_effect = [False, False] 193 parser = self.set_up_parser("torq.py -p simpleperf --symbols %s" 194 % SYMBOLS_PATH) 195 196 args = parser.parse_args() 197 args, error = verify_args(args) 198 199 self.assertEqual(error.message, "Invalid inputs.") 200 self.assertEqual(error.suggestion, "Set $ANDROID_BUILD_TOP to your android " 201 "root path and make sure you have " 202 "$ANDROID_BUILD_TOP/system/extras/" 203 "simpleperf/scripts downloaded.") 204 205 @mock.patch.dict(os.environ, {"ANDROID_BUILD_TOP": ANDROID_BUILD_TOP}, 206 clear=True) 207 @mock.patch.object(os.path, "exists", autospec=True) 208 @mock.patch.object(os.path, "isdir", autospec=True) 209 @mock.patch.object(builtins, "input") 210 def test_create_parser_download_scripts_refuse_download(self, mock_input, 211 mock_isdir, mock_exists): 212 mock_isdir.return_value = True 213 mock_input.return_value = "n" 214 mock_exists.side_effect = [False, False] 215 parser = self.set_up_parser("torq.py -p simpleperf --symbols %s" 216 % SYMBOLS_PATH) 217 218 args = parser.parse_args() 219 args, error = verify_args(args) 220 221 self.assertEqual(error.message, "Did not download simpleperf scripts.") 222 self.assertEqual(error.suggestion, "Set $ANDROID_BUILD_TOP to your android " 223 "root path and make sure you have " 224 "$ANDROID_BUILD_TOP/system/extras/" 225 "simpleperf/scripts downloaded.") 226 227 228if __name__ == '__main__': 229 unittest.main() 230