• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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