1# Copyright 2018 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6import os 7 8from autotest_lib.client.bin import utils 9from autotest_lib.client.common_lib import error 10from autotest_lib.client.common_lib.cros import arc 11from autotest_lib.client.cros.graphics import graphics_utils 12try: 13 # Importing this private util fails on public boards (e.g amd64-generic) 14 from autotest_lib.client.common_lib.cros import password_util 15except ImportError: 16 logging.error('Failed to import password_util from autotest-private') 17 18 19class cheets_AppCompatTest(arc.ArcTest): 20 """ 21 Autotest wrapper class for the AppCompat's team UIAutomator test cases. 22 23 It is used to call the apk that runs the test. It then copies logcat, 24 bugreport and screenshots to the autotest resultsdir. 25 26 It parses logcat to get the test results. 27 28 """ 29 version = 1 30 31 _PLAY_STORE_ACTIVITY = 'com.android.vending' 32 _TEST_FILES_LOCATION = ('https://storage.googleapis.com/chromeos-throw' 33 '-away-bucket/app_compat/') 34 _TEST_FILES = ['app-debug.apk', 'app-debug-androidTest.apk', 35 'autresources.xml'] 36 _TMP_LOCATION = '/tmp/app_compat/' 37 _LOG_TAG = '~APPCOM_TEST_AUTO~' 38 39 40 def initialize(self, pkg_name, touch_view_mode): 41 self._pkg_name = pkg_name 42 browser_args = None 43 self._touch_view_mode = touch_view_mode 44 if self._touch_view_mode: 45 browser_args = ['--force-tablet-mode=touch_view'] 46 47 cred = password_util.get_appcompat_credentials() 48 super(cheets_AppCompatTest, self).initialize( 49 disable_arc_opt_in=False, extra_browser_args=browser_args, 50 disable_app_sync=True, disable_play_auto_install=True, 51 username=cred.username, 52 password=cred.password) 53 54 55 def arc_setup(self): 56 super(cheets_AppCompatTest, self).arc_setup() 57 58 59 def cleanup(self): 60 arc.adb_cmd('uninstall com.hcl.actframework') 61 arc.adb_cmd('uninstall com.hcl.actframework.test') 62 arc.adb_cmd('uninstall %s' % self._pkg_name, ignore_status=True) 63 arc.adb_shell('rm -f /sdcard/autresources.xml > /dev/null') 64 arc.adb_shell('rm -f /sdcard/touchView.txt > /dev/null', 65 ignore_status=True) 66 utils.run('rm -rf %s' % self._TMP_LOCATION) 67 super(cheets_AppCompatTest, self).cleanup() 68 69 70 def _grant_storage_permission(self): 71 """Grant the UIAutomator tests storage permission.""" 72 arc.adb_shell('am instrument -w -r -e debug false -e ' 73 '"grant_permissions_only" "Y" ' 74 'com.hcl.actframework.test/android.support.test.runner' 75 '.AndroidJUnitRunner') 76 77 def _start_test(self): 78 """Kick off the UIAutomator tests.""" 79 arc.adb_shell('am instrument -w -r -e debug false -e ' 80 '"device_model" "Google~Pixelbook" -e ' 81 '"app_packagename" %s -e "app_version" "TBD" -e ' 82 '"device_os_build_version" 7.1.1 -e ' 83 '"clear_recents" "N" -e "check_wifi_connection" ' 84 '"N" -e "check_location_on" "N" -e ' 85 '"check_auto_rotate_off" "N" ' 86 'com.hcl.actframework.test/android.support.test' 87 '.runner.AndroidJUnitRunner' % self._pkg_name) 88 89 90 def _copy_resources_to_dut(self): 91 """Copy the apks & xml file needed for the UIAutomator tests.""" 92 if not os.path.exists(self._TMP_LOCATION): 93 os.mkdir(self._TMP_LOCATION) 94 for test_file in self._TEST_FILES: 95 uri = self._TEST_FILES_LOCATION + test_file 96 utils.run('wget -O %s %s' % (os.path.join(self._TMP_LOCATION, 97 test_file), uri)) 98 99 for test_file in os.listdir(self._TMP_LOCATION): 100 if test_file == 'app-debug.apk': 101 arc.adb_cmd('push %s /data/local/tmp/com.hcl.actframework' % 102 os.path.join(self._TMP_LOCATION, test_file)) 103 arc.adb_shell('pm install -t -r ' 104 '"/data/local/tmp/com.hcl.actframework"') 105 elif test_file == 'app-debug-androidTest.apk': 106 arc.adb_cmd('push %s ' 107 '/data/local/tmp/com.hcl.actframework.test' % 108 os.path.join(self._TMP_LOCATION, test_file)) 109 arc.adb_shell('pm install -t -r ' 110 '"/data/local/tmp/com.hcl.actframework.test"') 111 else: 112 arc.adb_cmd('push %s /sdcard/' % os.path.join( 113 self._TMP_LOCATION, test_file)) 114 if self._touch_view_mode: 115 arc.adb_shell('touch /sdcard/touchView.txt') 116 117 118 def _capture_bugreport(self): 119 """Captures a bugreport and saves into resultsdir.""" 120 arc.adb_cmd('bugreport > %s' % os.path.join(self.resultsdir, 121 'bugreport.txt')) 122 123 124 def _grab_screenshots(self): 125 """Captures screenshots that are created by the UIAutomator tests.""" 126 for screenshot in arc.adb_shell('find /sdcard/*.png', 127 ignore_status=True).splitlines(): 128 logging.debug('Screenshot is %s.', screenshot) 129 arc.adb_cmd('pull %s %s' % (screenshot, self.resultsdir), 130 ignore_status=True) 131 arc.adb_shell('rm -r %s' % screenshot, ignore_status=True) 132 133 134 def _save_logcat(self, iteration): 135 """Saves the logcat for the test run to the resultsdir.""" 136 self._logcat = 'logcat%d.txt' % iteration 137 arc.adb_cmd('logcat -d > %s' % os.path.join(self.resultsdir, 138 self._logcat)) 139 140 141 def _parse_results(self): 142 """Parse the pass/fail/blocked/skipped entries from logcat. """ 143 passed = self._get_log_entry_count(",PASS,") 144 failed = self._get_log_entry_count(",FAIL,") 145 nt = self._get_log_entry_count(",NT,") 146 blocked = self._get_log_entry_count(",BLOCKED,") 147 skipped = self._get_log_entry_count(",SKIPPED,") 148 ft = self._get_list_of_test_cases(",FAIL,") 149 bt = self._get_list_of_test_cases(",BLOCKED,") 150 151 result = ('Test results for %s(%s): Passed %s, Failed %s, Not Tested ' 152 '%s, Blocked %s, Skipped %s. Failed tests: [%s] Blocked tests: [%s]' % ( 153 self._pkg_name, self._app_version, passed, failed, nt, 154 blocked, skipped, ft, bt)) 155 logging.info(result) 156 pass_status = int(failed) == 0 and int(blocked) == 0 and int(passed) > 0 157 return pass_status, result 158 159 160 def _get_log_entry_count(self, entry): 161 """Get the total number of times a string appears in logcat.""" 162 logcat = os.path.join(self.resultsdir, self._logcat) 163 return utils.run('grep "%s" %s | grep -c "%s"' % 164 (self._LOG_TAG, logcat, entry), 165 ignore_status=True).stdout.strip() 166 167 168 def _get_list_of_test_cases(self, status): 169 """Get the list of test cases that are fail/blocked from logcat.""" 170 logcat = os.path.join(self.resultsdir, self._logcat) 171 fail_or_blocked_tests = [] 172 fail_or_blocked_tests_list = utils.run('grep "%s" %s | grep "%s"' % 173 (self._LOG_TAG, logcat, status), 174 ignore_status=True).stdout.strip().splitlines() 175 for line in fail_or_blocked_tests_list: 176 fail_or_blocked_tests.append(line.split(',')[-4:]) 177 return fail_or_blocked_tests 178 179 180 def _increase_logcat_buffer(self): 181 """Increase logcat buffer so all UIAutomator test entries appear.""" 182 arc.adb_cmd('logcat -G 16M') 183 184 185 def _clear_logcat_buffer(self): 186 """Clear logcat buffer between runs.""" 187 arc.adb_cmd('logcat -c') 188 189 190 def _get_app_version(self): 191 """Grab the version of the application we are testing.""" 192 self._app_version = arc.adb_shell('dumpsys package %s | grep ' 193 'versionName| cut -d"=" -f2' % 194 self._pkg_name) 195 196 197 def _take_screenshot(self, name): 198 try: 199 graphics_utils.take_screenshot(self.resultsdir, name) 200 except: 201 logging.info('Failed to take screenshot') 202 203 204 def run_once(self, retries=3): 205 """Main entry for the test.""" 206 self._increase_logcat_buffer() 207 self._copy_resources_to_dut() 208 self._grant_storage_permission() 209 210 for trial in range(retries): 211 logging.info('Iteration %d: Trying to launch play store', trial) 212 213 # Bring Play Store to front. 214 arc.adb_shell('am start %s' % self._PLAY_STORE_ACTIVITY) 215 self._take_screenshot('test_start') 216 self._start_test() 217 logging.info('Iteration %d: Test finished', trial) 218 self._take_screenshot('test_end') 219 self._get_app_version() 220 self._capture_bugreport() 221 self._grab_screenshots() 222 self._save_logcat(trial) 223 passed, result = self._parse_results() 224 if passed: 225 return 226 elif trial + 1 >= retries: 227 raise error.TestFail(result) 228 229 # Kill playstore and clear logcat for next iteration. 230 arc.adb_shell('am force-stop %s' % self._PLAY_STORE_ACTIVITY) 231 self._clear_logcat_buffer() 232