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