• 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
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