# Copyright 2018 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import logging import os from autotest_lib.client.bin import utils from autotest_lib.client.common_lib import error from autotest_lib.client.common_lib.cros import arc from autotest_lib.client.cros.graphics import graphics_utils class cheets_AppCompatTest(arc.ArcTest): """ Autotest wrapper class for the AppCompat's team UIAutomator test cases. It is used to call the apk that runs the test. It then copies logcat, bugreport and screenshots to the autotest resultsdir. It parses logcat to get the test results. """ version = 1 _PLAY_STORE_ACTIVITY = 'com.android.vending' _TEST_FILES_LOCATION = ('https://storage.googleapis.com/chromeos-throw' '-away-bucket/app_compat/') _TEST_FILES = ['app-debug.apk', 'app-debug-androidTest.apk', 'autresources.xml'] _TMP_LOCATION = '/tmp/app_compat/' _LOG_TAG = '~APPCOM_TEST_AUTO~' def initialize(self, pkg_name, touch_view_mode): self._pkg_name = pkg_name browser_args = None self._touch_view_mode = touch_view_mode if self._touch_view_mode: browser_args = ['--force-tablet-mode=touch_view'] super(cheets_AppCompatTest, self).initialize( disable_arc_opt_in=False, extra_browser_args=browser_args, disable_app_sync=True, disable_play_auto_install=True, username='crosarcappcompat@gmail.com', password='appcompatautotest') def arc_setup(self): super(cheets_AppCompatTest, self).arc_setup() def cleanup(self): arc.adb_cmd('uninstall com.hcl.actframework') arc.adb_cmd('uninstall com.hcl.actframework.test') arc.adb_cmd('uninstall %s' % self._pkg_name) arc.adb_shell('rm -f /sdcard/autresources.xml > /dev/null') arc.adb_shell('rm -f /sdcard/touchView.txt > /dev/null', ignore_status=True) utils.run('rm -rf %s' % self._TMP_LOCATION) super(cheets_AppCompatTest, self).cleanup() def _grant_storage_permission(self): """Grant the UIAutomator tests storage permission.""" arc.adb_shell('am instrument -w -r -e debug false -e ' '"grant_permissions_only" "Y" ' 'com.hcl.actframework.test/android.support.test.runner' '.AndroidJUnitRunner') def _start_test(self): """Kick off the UIAutomator tests.""" arc.adb_shell('am instrument -w -r -e debug false -e ' '"device_model" "Google~Pixelbook" -e ' '"app_packagename" %s -e "app_version" "TBD" -e ' '"device_os_build_version" 7.1.1 -e ' '"clear_recents" "N" -e "check_wifi_connection" ' '"N" -e "check_location_on" "N" -e ' '"check_auto_rotate_off" "N" ' 'com.hcl.actframework.test/android.support.test' '.runner.AndroidJUnitRunner' % self._pkg_name) def _copy_resources_to_dut(self): """Copy the apks & xml file needed for the UIAutomator tests.""" if not os.path.exists(self._TMP_LOCATION): os.mkdir(self._TMP_LOCATION) for test_file in self._TEST_FILES: uri = self._TEST_FILES_LOCATION + test_file utils.run('wget -O %s %s' % (os.path.join(self._TMP_LOCATION, test_file), uri)) for test_file in os.listdir(self._TMP_LOCATION): if test_file == 'app-debug.apk': arc.adb_cmd('push %s /data/local/tmp/com.hcl.actframework' % os.path.join(self._TMP_LOCATION, test_file)) arc.adb_shell('pm install -t -r ' '"/data/local/tmp/com.hcl.actframework"') elif test_file == 'app-debug-androidTest.apk': arc.adb_cmd('push %s ' '/data/local/tmp/com.hcl.actframework.test' % os.path.join(self._TMP_LOCATION, test_file)) arc.adb_shell('pm install -t -r ' '"/data/local/tmp/com.hcl.actframework.test"') else: arc.adb_cmd('push %s /sdcard/' % os.path.join( self._TMP_LOCATION, test_file)) if self._touch_view_mode: arc.adb_shell('touch /sdcard/touchView.txt') def _capture_bugreport(self): """Captures a bugreport and saves into resultsdir.""" arc.adb_cmd('bugreport > %s' % os.path.join(self.resultsdir, 'bugreport.txt')) def _grab_screenshots(self): """Captures screenshots that are created by the UIAutomator tests.""" for screenshot in arc.adb_shell('find /sdcard/*.png').splitlines(): logging.debug('Screenshot is %s.', screenshot) arc.adb_cmd('pull %s %s' % (screenshot, self.resultsdir), ignore_status=True) arc.adb_shell('rm -r %s' % screenshot, ignore_status=True) def _save_logcat(self, iteration): """Saves the logcat for the test run to the resultsdir.""" self._logcat = 'logcat%d.txt' % iteration arc.adb_cmd('logcat -d > %s' % os.path.join(self.resultsdir, self._logcat)) def _parse_results(self): """Parse the pass/fail/skipped entries from logcat. """ passed = self._get_log_entry_count(",PASS,") failed = self._get_log_entry_count(",FAIL,") nt = self._get_log_entry_count(",NT,") blocked = self._get_log_entry_count(",BLOCKED,") skipped = self._get_log_entry_count(",SKIPPED,") ft = self._get_failed_test_cases() result = ('Test results for %s(%s): Passed %s, Failed %s, Not Tested ' '%s, Blocked %s, Skipped %s. Failed tests: [%s]' % ( self._pkg_name, self._app_version, passed, failed, nt, blocked, skipped, ft)) logging.info(result) pass_status = int(failed) == 0 and int(passed) > 0 return pass_status, result def _get_log_entry_count(self, entry): """Get the total number of times a string appears in logcat.""" logcat = os.path.join(self.resultsdir, self._logcat) return utils.run('grep "%s" %s | grep -c "%s"' % (self._LOG_TAG, logcat, entry), ignore_status=True).stdout.strip() def _get_failed_test_cases(self): """Get the list of test cases that failed from logcat.""" logcat = os.path.join(self.resultsdir, self._logcat) failed_tests = [] failed_tests_list = utils.run('grep "%s" %s | grep ",FAIL,"' % (self._LOG_TAG, logcat), ignore_status=True).stdout.strip().splitlines() for line in failed_tests_list: failed_tests.append(line.split(',')[-4:]) return failed_tests def _increase_logcat_buffer(self): """Increase logcat buffer so all UIAutomator test entries appear.""" arc.adb_cmd('logcat -G 16M') def _clear_logcat_buffer(self): """Clear logcat buffer between runs.""" arc.adb_cmd('logcat -c') def _get_app_version(self): """Grab the version of the application we are testing.""" self._app_version = arc.adb_shell('dumpsys package %s | grep ' 'versionName| cut -d"=" -f2' % self._pkg_name) def _take_screenshot(self, name): try: graphics_utils.take_screenshot(self.resultsdir, name) except: logging.info('Failed to take screenshot') def run_once(self, retries=3): self._increase_logcat_buffer() self._copy_resources_to_dut() self._grant_storage_permission() for trial in range(retries): logging.info('Iteration %d: Trying to launch play store' % trial) # Bring Play Store to front. arc.adb_shell('am start %s' % self._PLAY_STORE_ACTIVITY) self._take_screenshot('test_start') self._start_test() logging.info('Iteration %d: Test finished' % trial) self._take_screenshot('test_end') self._get_app_version() self._capture_bugreport() self._grab_screenshots() self._save_logcat(trial) passed, result = self._parse_results() if passed: return elif trial + 1 >= retries: raise error.TestFail(result) # Kill playstore and clear logcat for next iteration. arc.adb_shell('am force-stop %s' % self._PLAY_STORE_ACTIVITY) self._clear_logcat_buffer()