293 lines
11 KiB
Python
293 lines
11 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
#
|
||
|
|
# Copyright 2019 - The Android Open Source Project
|
||
|
|
#
|
||
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
|
# you may not use this file except in compliance with the License.
|
||
|
|
# You may obtain a copy of the License at
|
||
|
|
#
|
||
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
#
|
||
|
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
|
# See the License for the specific language governing permissions and
|
||
|
|
# limitations under the License.
|
||
|
|
|
||
|
|
import re
|
||
|
|
import time
|
||
|
|
|
||
|
|
from acts import base_test
|
||
|
|
from acts.libs.proc import job
|
||
|
|
from acts import signals
|
||
|
|
from acts.test_decorators import test_tracker_info
|
||
|
|
|
||
|
|
# Time it takes for the usb tethering IP to show up in ifconfig.
|
||
|
|
IFCONFIG_SETTLE_TIME = 5
|
||
|
|
USB_CHARGE_MODE = 'svc usb setFunctions'
|
||
|
|
USB_TETHERING_MODE = 'svc usb setFunctions rndis'
|
||
|
|
DEVICE_IP_ADDRESS = 'ip address'
|
||
|
|
|
||
|
|
|
||
|
|
class UsbTetheringThroughputTest(base_test.BaseTestClass):
|
||
|
|
"""Tests for usb tethering throughput test.
|
||
|
|
|
||
|
|
Test Bed Requirement:
|
||
|
|
* One Android device.
|
||
|
|
* Sim card with data call.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def setup_class(self):
|
||
|
|
""" Setup devices for usb tethering """
|
||
|
|
self.dut = self.android_devices[0]
|
||
|
|
self.ip_server = self.iperf_servers[0]
|
||
|
|
self.port_num = self.ip_server.port
|
||
|
|
req_params = [
|
||
|
|
'iperf_usb_3_criteria', 'iperf_usb_2_criteria', 'controller_path',
|
||
|
|
'iperf_test_sec'
|
||
|
|
]
|
||
|
|
self.unpack_userparams(req_param_names=req_params)
|
||
|
|
if self.dut.model in self.user_params.get('legacy_projects', []):
|
||
|
|
self.usb_controller_path = self.user_params[
|
||
|
|
'legacy_controller_path']
|
||
|
|
else:
|
||
|
|
self.usb_controller_path = self.controller_path
|
||
|
|
|
||
|
|
def setup_test(self):
|
||
|
|
self.dut.adb.wait_for_device()
|
||
|
|
self.dut.droid.wakeLockAcquireBright()
|
||
|
|
self.dut.droid.wakeUpNow()
|
||
|
|
self.dut.unlock_screen()
|
||
|
|
|
||
|
|
def teardown_test(self):
|
||
|
|
self.dut.droid.wakeLockRelease()
|
||
|
|
self.dut.droid.goToSleepNow()
|
||
|
|
# Reboot device to avoid the side effect that cause adb missing after echo usb speed.
|
||
|
|
self.dut.reboot()
|
||
|
|
|
||
|
|
def on_fail(self, test_name, begin_time):
|
||
|
|
self.dut.take_bug_report(test_name, begin_time)
|
||
|
|
self.dut.cat_adb_log(test_name, begin_time)
|
||
|
|
|
||
|
|
def enable_usb_tethering(self):
|
||
|
|
"""Stop SL4A service and enable usb tethering.
|
||
|
|
|
||
|
|
Logic steps are
|
||
|
|
1. Stop SL4A service.
|
||
|
|
2. Enable usb tethering.
|
||
|
|
3. Restart SL4A service.
|
||
|
|
4. Check usb tethering enabled.
|
||
|
|
|
||
|
|
Raises:
|
||
|
|
Signals.TestFailure is raised by not find rndis string.
|
||
|
|
"""
|
||
|
|
self.dut.stop_services()
|
||
|
|
self.dut.adb.shell(USB_TETHERING_MODE, ignore_status=True)
|
||
|
|
self.dut.adb.wait_for_device()
|
||
|
|
self.dut.start_services()
|
||
|
|
if 'rndis' not in self.dut.adb.shell(DEVICE_IP_ADDRESS):
|
||
|
|
raise signals.TestFailure('Unable to enable USB tethering.')
|
||
|
|
|
||
|
|
def get_pc_tethering_ip(self):
|
||
|
|
"""Check usb tethering IP from PC.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Usb tethering IP from PC.
|
||
|
|
|
||
|
|
Raises:
|
||
|
|
Signals.TestFailure is raised by not find usb tethering IP.
|
||
|
|
"""
|
||
|
|
time.sleep(IFCONFIG_SETTLE_TIME)
|
||
|
|
check_usb_tethering = job.run('ifconfig').stdout
|
||
|
|
matches = re.findall('inet (\d+.\d+.42.\d+)', check_usb_tethering)
|
||
|
|
if not matches:
|
||
|
|
raise signals.TestFailure(
|
||
|
|
'Unable to find tethering IP. The device may not be tethered.')
|
||
|
|
else:
|
||
|
|
return matches[0]
|
||
|
|
|
||
|
|
def get_dut_tethering_ip(self):
|
||
|
|
"""Check usb tethering IP from Android device.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Usb tethering IP from Android device.
|
||
|
|
|
||
|
|
Raises:
|
||
|
|
Signals.TestFailure is raised by not find usb tethering IP.
|
||
|
|
"""
|
||
|
|
time.sleep(IFCONFIG_SETTLE_TIME)
|
||
|
|
check_usb_tethering = self.dut.adb.shell('ifconfig')
|
||
|
|
matches = re.findall('addr:(\d+.\d+.42.\d+)', check_usb_tethering)
|
||
|
|
if not matches:
|
||
|
|
raise signals.TestFailure(
|
||
|
|
'Unable to find tethering IP. The device may not be tethered.')
|
||
|
|
else:
|
||
|
|
return matches[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 dut_can_ping(self, count=3):
|
||
|
|
"""Run ping traffic from Android device side.
|
||
|
|
|
||
|
|
Logic steps are
|
||
|
|
1. Android device ping the 8.8.8.8.
|
||
|
|
2. Check the packet loss rate.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
count : count for ping test.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
True: If no packet loss.
|
||
|
|
False: Otherwise.
|
||
|
|
"""
|
||
|
|
ip = '8.8.8.8'
|
||
|
|
ping = self.dut.adb.shell(
|
||
|
|
'ping -c {} {}'.format(count, ip), ignore_status=True)
|
||
|
|
self.log.info(ping)
|
||
|
|
return '0% packet loss' in ping
|
||
|
|
|
||
|
|
def run_iperf_client(self, dut_ip, extra_params=''):
|
||
|
|
"""Run iperf client command after iperf server enabled.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
dut_ip: string which contains the ip address.
|
||
|
|
extra_params: params to be added to the iperf client.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Success: True if the iperf execute. False otherwise.
|
||
|
|
Rate: throughput data.
|
||
|
|
"""
|
||
|
|
self.log.info('Run iperf process.')
|
||
|
|
cmd = "iperf3 -c {} {} -p {}".format(dut_ip, extra_params,
|
||
|
|
self.port_num)
|
||
|
|
self.log.info(cmd)
|
||
|
|
try:
|
||
|
|
result = self.dut.adb.shell(cmd, ignore_status=True)
|
||
|
|
self.log.info(result)
|
||
|
|
except:
|
||
|
|
self.log.error('Fail to execute iperf client.')
|
||
|
|
return False, 0
|
||
|
|
rate = re.findall('(\d+.\d+) (.)bits/sec.*receiver', result)
|
||
|
|
return True, rate[0][0], rate[0][1]
|
||
|
|
|
||
|
|
def run_iperf_tx_rx(self, usb_speed, criteria):
|
||
|
|
"""Run iperf tx and rx.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
usb_speed: string which contains the speed info.
|
||
|
|
criteria: usb performance criteria.
|
||
|
|
|
||
|
|
Raises:
|
||
|
|
Signals.TestFailure is raised by usb tethering under criteria.
|
||
|
|
"""
|
||
|
|
self.enable_usb_tethering()
|
||
|
|
self.dut.adb.wait_for_device()
|
||
|
|
self.ip_server.start()
|
||
|
|
pc_ip = self.get_pc_tethering_ip()
|
||
|
|
tx_success, tx_rate, tx_unit = self.run_iperf_client(
|
||
|
|
pc_ip, '-t{} -i1 -w2M'.format(self.iperf_test_sec))
|
||
|
|
rx_success, rx_rate, rx_unit = self.run_iperf_client(
|
||
|
|
pc_ip, '-t{} -i1 -w2M -R'.format(self.iperf_test_sec))
|
||
|
|
self.log.info('TestResult iperf_{}_rx'.format(usb_speed) + rx_rate +
|
||
|
|
' ' + rx_unit + 'bits/sec')
|
||
|
|
self.log.info('TestResult iperf_{}_tx'.format(usb_speed) + tx_rate +
|
||
|
|
' ' + tx_unit + 'bits/sec')
|
||
|
|
self.ip_server.stop()
|
||
|
|
if not tx_success or (float(tx_rate) < criteria and tx_unit != "G"):
|
||
|
|
raise signals.TestFailure('Iperf {}_tx test is {} {}bits/sec, '
|
||
|
|
'the throughput result failed.'.format(
|
||
|
|
usb_speed, tx_rate, tx_unit))
|
||
|
|
if not rx_success or (float(rx_rate) < criteria and rx_unit != "G"):
|
||
|
|
raise signals.TestFailure('Iperf {}_rx test is {} {}bits/sec, '
|
||
|
|
'the throughput result failed.'.format(
|
||
|
|
usb_speed, rx_rate, rx_unit))
|
||
|
|
|
||
|
|
def get_usb_speed(self):
|
||
|
|
"""Get current usb speed."""
|
||
|
|
usb_controller_address = self.dut.adb.shell(
|
||
|
|
'getprop sys.usb.controller', ignore_status=True)
|
||
|
|
usb_speed = self.dut.adb.shell(
|
||
|
|
'cat sys/class/udc/{}/current_speed'.format(
|
||
|
|
usb_controller_address))
|
||
|
|
return usb_speed, usb_controller_address
|
||
|
|
|
||
|
|
@test_tracker_info(uuid="e7e0dfdc-3d1c-4642-a468-27326c49e4cb")
|
||
|
|
def test_tethering_ping(self):
|
||
|
|
"""Enable usb tethering then executing ping test.
|
||
|
|
|
||
|
|
Steps:
|
||
|
|
1. Stop SL4A service.
|
||
|
|
2. Enable usb tethering.
|
||
|
|
3. Restart SL4A service.
|
||
|
|
4. Execute ping test from PC and Android Device.
|
||
|
|
5. Check the ping lost rate.
|
||
|
|
"""
|
||
|
|
self.enable_usb_tethering()
|
||
|
|
if self.pc_can_ping() and self.dut_can_ping():
|
||
|
|
raise signals.TestPass(
|
||
|
|
'Ping test is passed. Network is reachable.')
|
||
|
|
raise signals.TestFailure(
|
||
|
|
'Ping test failed. Maybe network is unreachable.')
|
||
|
|
|
||
|
|
@test_tracker_info(uuid="8263c880-8a7e-4a68-b47f-e7caba3e9968")
|
||
|
|
def test_usb_tethering_iperf_super_speed(self):
|
||
|
|
"""Enable usb tethering then executing iperf test.
|
||
|
|
|
||
|
|
Steps:
|
||
|
|
1. Stop SL4A service.
|
||
|
|
2. Enable usb tethering.
|
||
|
|
3. Restart SL4A service.
|
||
|
|
4. Skip test if device not support super-speed.
|
||
|
|
5. Execute iperf test for usb tethering and get the throughput result.
|
||
|
|
6. Check the iperf throughput result.
|
||
|
|
"""
|
||
|
|
if (self.get_usb_speed()[0] != 'super-speed'):
|
||
|
|
raise signals.TestSkip(
|
||
|
|
'USB 3 not available for the device, skip super-speed performance test.'
|
||
|
|
)
|
||
|
|
self.run_iperf_tx_rx('usb_3', self.iperf_usb_3_criteria)
|
||
|
|
|
||
|
|
@test_tracker_info(uuid="5d8a22fd-1f9b-4758-a6b4-855d134b348a")
|
||
|
|
def test_usb_tethering_iperf_high_speed(self):
|
||
|
|
"""Enable usb tethering then executing iperf test.
|
||
|
|
|
||
|
|
Steps:
|
||
|
|
1. Stop SL4A service.
|
||
|
|
2. Enable usb tethering.
|
||
|
|
3. Restart SL4A service.
|
||
|
|
4. Force set usb speed to high-speed if default is super-speed.
|
||
|
|
5. Execute iperf test for usb tethering and get the throughput result.
|
||
|
|
6. Check the iperf throughput result.
|
||
|
|
"""
|
||
|
|
if (self.get_usb_speed()[0] != 'high-speed'):
|
||
|
|
self.log.info(
|
||
|
|
'Default usb speed is USB 3,Force set usb to high-speed.')
|
||
|
|
self.dut.stop_services()
|
||
|
|
self.dut.adb.wait_for_device()
|
||
|
|
self.dut.adb.shell(
|
||
|
|
'echo high > {}{}.ssusb/speed'.format(
|
||
|
|
self.usb_controller_path,
|
||
|
|
self.get_usb_speed()[1].strip('.dwc3')),
|
||
|
|
ignore_status=True)
|
||
|
|
self.dut.adb.wait_for_device()
|
||
|
|
self.dut.start_services()
|
||
|
|
self.run_iperf_tx_rx('usb_2', self.iperf_usb_2_criteria)
|