Exemple #1
0
    def pc_can_ping(self, count=3):
        """Run ping traffic from PC side.

        Logic steps are
        1. PC ping the usb server ip.
        2. Check the packet loss rate.

        Args:
            count : count for ping test.

        Returns:
            True: If no packet loss.
            False: Otherwise.
        """
        ip = self.get_dut_tethering_ip()
        ping = job.run('ping -c {} {}'.format(count, ip),
                       ignore_status=True).stdout
        self.log.info(ping)
        return '0% packet loss' in ping
def main():
    if COMMIT_ID_ENV_KEY not in os.environ:
        logging.error('Missing commit id in environment.')
        exit(1)

    # get list of *.proto and *_pb2.py files from commit, then compare
    proto_files = []
    proto_gen_files = []
    git_cmd = GIT_FILE_NAMES_CMD % os.environ[COMMIT_ID_ENV_KEY]
    lines = job.run(git_cmd).stdout.splitlines()
    for line in lines:
        match = re.match(r'(\S+)\s+(.*)', line)
        status, f = match.group(1), match.group(2)
        if status != 'D':
            if f.endswith('.proto'):
                proto_files.append(os.path.abspath(f))
            if f.endswith('_pb2.py'):
                proto_gen_files.append(os.path.abspath(f))
    exit(not verify_protos_update_generated_files(proto_files, proto_gen_files))
    def get_rndis_interface(self):
        """Check rndis interface after usb tethering enable.

        Returns:
            Usb tethering interface from Android device.

        Raises:
            TestFailure when unable to find correct usb tethering interface.
        """
        time.sleep(DEFAULT_SETTLE_TIME)
        check_usb_tethering = job.run('ifconfig').stdout
        # A regex that stores the tethering interface in group 1.
        tethered_interface_regex = r'^(enp.*?):.*?broadcast 192.168.42.255'
        match = re.search(tethered_interface_regex, check_usb_tethering,
                          re.DOTALL + re.MULTILINE)
        if match:
            return match.group(1)
        else:
            raise signals.TestFailure(
                'Unable to find tethering interface. The device may not be tethered.'
            )
Exemple #4
0
 def _exec_fastboot_cmd(self,
                        name,
                        arg_str,
                        ignore_status=False,
                        timeout=60):
     command = ' '.join((self.fastboot_str, name, arg_str))
     if self.ssh_connection:
         result = self.connection.run(command,
                                      ignore_status=True,
                                      timeout=timeout)
     else:
         result = job.run(command, ignore_status=True, timeout=timeout)
     ret, out, err = result.exit_status, result.stdout, result.stderr
     # TODO: This is only a temporary workaround for b/34815412.
     # fastboot getvar outputs to stderr instead of stdout
     if "getvar" in command:
         out = err
     if ret == 0 or ignore_status:
         return out
     else:
         raise FastbootError(
             cmd=command, stdout=out, stderr=err, ret_code=ret)
Exemple #5
0
    def start(self, extra_args='', tag=''):
        """Starts iperf server on local machine.

        Args:
            extra_args: A string representing extra arguments to start iperf
                server with.
            tag: Appended to log file name to identify logs from different
                iperf runs.
        """
        if self._iperf_process is not None:
            return

        self._current_log_file = self._get_full_file_path(tag)

        # Run an iperf3 server on the hinted port with JSON output.
        command = ['iperf3', '-s', '-p', str(self._hinted_port), '-J']

        command.extend(shlex.split(extra_args))

        if self._last_opened_file:
            self._last_opened_file.close()
        self._last_opened_file = open(self._current_log_file, 'w')
        self._iperf_process = subprocess.Popen(command,
                                               stdout=self._last_opened_file,
                                               stderr=subprocess.DEVNULL)
        for attempts_left in reversed(range(3)):
            try:
                self._port = int(
                    _get_port_from_ss_output(
                        job.run('ss -l -p -n | grep iperf').stdout,
                        self._iperf_process.pid))
                break
            except ProcessLookupError:
                if attempts_left == 0:
                    raise
                logging.debug('iperf3 process not started yet.')
                time.sleep(.01)
 def test_run_no_shell(self, popen):
     """Test that we handle running without a wrapping shell."""
     result = job.run(['echo', 'TEST'])
     self.assertTrue(result.stdout.startswith('TEST'))
 def test_run_with_ignored_error(self, popen):
     """Test that we can ignore exit status on request."""
     result = job.run('exit 1', ignore_status=True)
     self.assertEqual(result.exit_status, 1)
 def test_run_stderr(self, popen):
     """Test that we can read process stderr."""
     result = job.run('echo TEST 1>&2')
     self.assertEqual(len(result.stdout), 0)
     self.assertTrue(result.stderr.startswith('TEST'))
     self.assertFalse(result.stdout)
 def test_run_success(self, popen):
     """Test running a simple shell command."""
     result = job.run('echo TEST')
     self.assertTrue(result.stdout.startswith('TEST'))
Exemple #10
0
    def pull_test_results(self, testplan_directory):
        """ Downloads the test reports from the remote host and parses the test
        summary to obtain the results.

        Args:
            testplan_directory: directory where to look for reports generated
                by the test equipment in the remote computer

        Returns:
             a JSON object containing the test results
        """

        if not testplan_directory:
            raise ValueError('Invalid testplan directory.')

        # Download test reports from the remote host
        job.run('wget -r --user={} --password={} -P {} ftp://{}/{}'.format(
            self.ftp_user, self.ftp_pass, logging.log_path,
            self.remote_server_ip, testplan_directory))

        # Open the testplan directory
        testplan_path = os.path.join(logging.log_path, self.remote_server_ip,
                                     testplan_directory)

        # Find the report.json file in the testcase folder
        dir_list = os.listdir(testplan_path)
        xml_path = None

        for dir in dir_list:
            if 'TestCaseName' in dir:
                xml_path = os.path.join(testplan_path, dir,
                                        'SummaryReport.xml')
                break

        if not xml_path:
            raise RuntimeError('Could not find testcase directory.')

        # Return the obtained report as a dictionary
        xml_tree = ElementTree.ElementTree()
        xml_tree.parse(source=xml_path)

        results_dictionary = {}

        col_iterator = xml_tree.iter('column')
        for col in col_iterator:
            # Look in the text of the first child for the required metrics
            if col.text == '2D position error [m]':
                results_dictionary[self.POS_ERROR_KEY] = {
                    'min': float(next(col_iterator).text),
                    'med': float(next(col_iterator).text),
                    'avg': float(next(col_iterator).text),
                    'max': float(next(col_iterator).text)
                }
            elif col.text == 'Time to first fix [s]':
                results_dictionary[self.TTFF_KEY] = {
                    'min': float(next(col_iterator).text),
                    'med': float(next(col_iterator).text),
                    'avg': float(next(col_iterator).text),
                    'max': float(next(col_iterator).text)
                }

        message_iterator = xml_tree.iter('message')
        for message in message_iterator:
            # Look for the line showing sensitivity
            if message.text:
                # The typo in 'successfull' is intended as it is present in the
                # test logs generated by the Contest system.
                match = re.search(
                    '(?<=Margin search completed, the lowest '
                    'successfull output power is )-?\d+.?\d+'
                    '(?= dBm)', message.text)
                if match:
                    results_dictionary[self.SENSITIVITY_KEY] = float(
                        match.group(0))
                    break

        return results_dictionary
Exemple #11
0
 def args(self, *args, **kwargs):
     return job.run(' '.join((self.fastboot_str, ) + args), **kwargs).stdout
Exemple #12
0
    def run(self,
            command,
            timeout=60,
            ignore_status=False,
            env=None,
            io_encoding='utf-8',
            attempts=2):
        """Runs a remote command over ssh.

        Will ssh to a remote host and run a command. This method will
        block until the remote command is finished.

        Args:
            command: The command to execute over ssh. Can be either a string
                     or a list.
            timeout: number seconds to wait for command to finish.
            ignore_status: bool True to ignore the exit code of the remote
                           subprocess.  Note that if you do ignore status codes,
                           you should handle non-zero exit codes explicitly.
            env: dict environment variables to setup on the remote host.
            io_encoding: str unicode encoding of command output.
            attempts: Number of attempts before giving up on command failures.

        Returns:
            A job.Result containing the results of the ssh command.

        Raises:
            job.TimeoutError: When the remote command took to long to execute.
            Error: When the ssh connection failed to be created.
            CommandError: Ssh worked, but the command had an error executing.
        """
        if attempts == 0:
            return None
        if env is None:
            env = {}

        try:
            self.setup_master_ssh(self._settings.connect_timeout)
        except Error:
            self.log.warning('Failed to create master ssh connection, using '
                             'normal ssh connection.')

        extra_options = {'BatchMode': True}
        if self._master_ssh_proc:
            extra_options['ControlPath'] = self.socket_path

        identifier = str(uuid.uuid4())
        full_command = 'echo "CONNECTED: %s"; %s' % (identifier, command)

        terminal_command = self._formatter.format_command(
            full_command, env, self._settings, extra_options=extra_options)

        dns_retry_count = 2
        while True:
            result = job.run(terminal_command,
                             ignore_status=True,
                             timeout=timeout,
                             io_encoding=io_encoding)
            output = result.stdout

            # Check for a connected message to prevent false negatives.
            valid_connection = re.search('^CONNECTED: %s' % identifier,
                                         output,
                                         flags=re.MULTILINE)
            if valid_connection:
                # Remove the first line that contains the connect message.
                line_index = output.find('\n') + 1
                if line_index == 0:
                    line_index = len(output)
                real_output = output[line_index:].encode(io_encoding)

                result = job.Result(command=result.command,
                                    stdout=real_output,
                                    stderr=result._raw_stderr,
                                    exit_status=result.exit_status,
                                    duration=result.duration,
                                    did_timeout=result.did_timeout,
                                    encoding=io_encoding)
                if result.exit_status and not ignore_status:
                    raise job.Error(result)
                return result

            error_string = result.stderr

            had_dns_failure = (result.exit_status == 255 and re.search(
                r'^ssh: .*: Name or service not known',
                error_string,
                flags=re.MULTILINE))
            if had_dns_failure:
                dns_retry_count -= 1
                if not dns_retry_count:
                    raise Error('DNS failed to find host.', result)
                self.log.debug('Failed to connect to host, retrying...')
            else:
                break

        had_timeout = re.search(
            r'^ssh: connect to host .* port .*: '
            r'Connection timed out\r$',
            error_string,
            flags=re.MULTILINE)
        if had_timeout:
            raise Error('Ssh timed out.', result)

        permission_denied = 'Permission denied' in error_string
        if permission_denied:
            raise Error('Permission denied.', result)

        unknown_host = re.search(
            r'ssh: Could not resolve hostname .*: '
            r'Name or service not known',
            error_string,
            flags=re.MULTILINE)
        if unknown_host:
            raise Error('Unknown host.', result)

        self.log.error('An unknown error has occurred. Job result: %s' %
                       result)
        ping_output = job.run('ping %s -c 3 -w 1' % self._settings.hostname,
                              ignore_status=True)
        self.log.error('Ping result: %s' % ping_output)
        if attempts > 1:
            self._cleanup_master_ssh()
            self.run(command, timeout, ignore_status, env, io_encoding,
                     attempts - 1)
        raise Error('The job failed for unknown reasons.', result)
Exemple #13
0
 def _make_phone_call(self, call_verification_func=None):
     ads = self.android_devices[:]
     if not self.single_phone_test:
         random.shuffle(ads)
     the_number = self.result_info["Call Total"] + 1
     duration = random.randrange(self.min_phone_call_duration,
                                 self.max_phone_call_duration)
     result = True
     test_name = "%s_No_%s_phone_call" % (self.test_name, the_number)
     log_msg = "[Test Case] %s" % test_name
     self.log.info("%s for %s seconds begin", log_msg, duration)
     begin_time = get_device_epoch_time(ads[0])
     for ad in self.android_devices:
         if self.user_params.get("turn_on_tcpdump", True):
             start_adb_tcpdump(ad, interface="any", mask="all")
         if not getattr(ad, "droid", None):
             ad.droid, ad.ed = ad.get_droid()
             ad.ed.start()
         else:
             try:
                 if not ad.droid.is_live:
                     ad.droid, ad.ed = ad.get_droid()
                     ad.ed.start()
                 else:
                     ad.ed.clear_all_events()
             except Exception:
                 ad.log.info("Create new sl4a session for phone call")
                 ad.droid, ad.ed = ad.get_droid()
                 ad.ed.start()
         ad.droid.logI("%s begin" % log_msg)
     start_qxdm_loggers(self.log, self.android_devices, begin_time)
     failure_reasons = set()
     self.dut_incall = True
     if self.single_phone_test:
         call_setup_result = initiate_call(
             self.log,
             self.dut,
             self.call_server_number,
             incall_ui_display=INCALL_UI_DISPLAY_BACKGROUND
         ) and wait_for_in_call_active(self.dut, 60, 3)
     else:
         call_setup_result = call_setup_teardown(
             self.log,
             ads[0],
             ads[1],
             ad_hangup=None,
             verify_caller_func=call_verification_func,
             verify_callee_func=call_verification_func,
             wait_time_in_call=0,
             incall_ui_display=INCALL_UI_DISPLAY_BACKGROUND)
     if not call_setup_result:
         call_logs = ads[0].search_logcat(
             "ActivityManager: START u0 {act=android.intent.action.CALL",
             begin_time)
         messaging_logs = ads[0].search_logcat(
             "com.google.android.apps.messaging/.ui.conversation.ConversationActivity",
             begin_time)
         if call_logs and messaging_logs:
             if messaging_logs[-1]["datetime_obj"] - call_logs[-1]["datetime_obj"] < 5:
                 ads[0].log.info(
                     "Call setup failure due to simultaneous activities")
                 self.result_info[
                     "Call Setup Failure With Simultaneous Activity"] += 1
                 return True
         self.log.error("%s: Setup Call failed.", log_msg)
         failure_reasons.add("Setup")
         result = False
     else:
         elapsed_time = 0
         check_interval = 5
         while (elapsed_time < duration):
             check_interval = min(check_interval, duration - elapsed_time)
             time.sleep(check_interval)
             elapsed_time += check_interval
             time_message = "at <%s>/<%s> second." % (elapsed_time,
                                                      duration)
             for ad in ads:
                 if not call_verification_func(self.log, ad):
                     ad.log.warning("Call is NOT in correct %s state at %s",
                                    call_verification_func.__name__,
                                    time_message)
                     if call_verification_func.__name__ == "is_phone_in_call_iwlan":
                         if is_phone_in_call(self.log, ad):
                             if getattr(ad, "data_rat_state_error_count",
                                        0) < 1:
                                 setattr(ad, "data_rat_state_error_count",
                                         1)
                                 continue
                     failure_reasons.add("Maintenance")
                     last_call_drop_reason(ad, begin_time)
                     hangup_call(self.log, ads[0])
                     result = False
                 else:
                     ad.log.info("Call is in correct %s state at %s",
                                 call_verification_func.__name__,
                                 time_message)
             if not result:
                 break
     if not hangup_call(self.log, ads[0]):
         failure_reasons.add("Teardown")
         result = False
     for ad in ads:
         if not wait_for_call_id_clearing(ad,
                                          []) or ad.droid.telecomIsInCall():
             ad.log.error("Fail to hang up call")
             failure_reasons.add("Teardown")
             result = False
     self.result_info["Call Total"] += 1
     for ad in self.android_devices:
         try:
             ad.droid.logI("%s end" % log_msg)
         except:
             pass
     self.log.info("%s end", log_msg)
     self.dut_incall = False
     if not result:
         self.log.info("%s failed", log_msg)
         if self.gps_log_file:
             gps_info = job.run(
                 "tail %s" % self.gps_log_file, ignore_status=True)
             if gps_info.stdout:
                 gps_log_path = os.path.join(self.log_path, test_name,
                                             "gps_logs.txt")
                 utils.create_dir(gps_log_path)
                 job.run(
                     "tail %s > %s" % (self.gps_log_file, gps_log_path),
                     ignore_status=True)
                 self.log.info("gps log:\n%s", gps_info.stdout)
             else:
                 self.log.warning("Fail to get gps log %s",
                                  self.user_params["gps_log_file"])
         for reason in failure_reasons:
             self.result_info["Call %s Failure" % reason] += 1
         for ad in ads:
             log_path = os.path.join(self.log_path, test_name,
                                     "%s_binder_logs" % ad.serial)
             utils.create_dir(log_path)
             ad.pull_files(BINDER_LOGS, log_path)
         try:
             self._take_bug_report(test_name, begin_time)
         except Exception as e:
             self.log.exception(e)
         for ad in ads:
             if ad.droid.telecomIsInCall():
                 hangup_call_by_adb(ad)
     else:
         self.log.info("%s test succeed", log_msg)
         self.result_info["Call Success"] += 1
         if self.result_info["Call Total"] % 50 == 0:
             for ad in ads:
                 synchronize_device_time(ad)
                 if not check_is_wifi_connected(self.log, ad,
                                                self.wifi_network_ssid):
                     ensure_wifi_connected(self.log, ad,
                                           self.wifi_network_ssid,
                                           self.wifi_network_pass)
                     force_connectivity_metrics_upload(ad)
                     time.sleep(300)
                     wifi_toggle_state(self.log, ad, False)
                 if self.get_binder_logs:
                     log_path = os.path.join(self.log_path,
                                             "%s_binder_logs" % test_name,
                                             "%s_binder_logs" % ad.serial)
                     utils.create_dir(log_path)
                     ad.pull_files(BINDER_LOGS, log_path)
     return result