You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
6.6 KiB
164 lines
6.6 KiB
7 months ago
|
#!/usr/bin/python2
|
||
|
# Copyright (c) 2011 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 cellular_logging
|
||
|
import dbus, os, subprocess, time
|
||
|
|
||
|
from autotest_lib.client.common_lib import error
|
||
|
from autotest_lib.client.cros import flimflam_test_path
|
||
|
from autotest_lib.client.cros.cellular import modem
|
||
|
|
||
|
log = cellular_logging.SetupCellularLogging('mm_test')
|
||
|
|
||
|
|
||
|
class ModemManagerTest(object):
|
||
|
"""Wrapper for starting up ModemManager in an artificial testing
|
||
|
environment, connected to a fake modem program and talking to a
|
||
|
fake (tun) network device.
|
||
|
|
||
|
The test using this must ensure the setup of the fakegudev and
|
||
|
fakemodem deps.
|
||
|
"""
|
||
|
|
||
|
def __init__(self, autodir, modem_pattern_files):
|
||
|
self.autodir=autodir # not great. Examine deps directly?
|
||
|
self.modem_pattern_files = modem_pattern_files
|
||
|
self.modemmanager = None
|
||
|
self.fakemodem_process = None
|
||
|
self.fakenet_process = None
|
||
|
|
||
|
def _start_fake_network(self):
|
||
|
"""Start the fakenetwork program and return the fake interface name
|
||
|
|
||
|
Start up the fakenet program, which uses the tun driver to create
|
||
|
a network device.
|
||
|
|
||
|
Returns the name of the fake network interface.
|
||
|
Sets self.fakenet_process as a handle to the process.
|
||
|
"""
|
||
|
self.fakenet_process = subprocess.Popen(
|
||
|
os.path.join(self.autodir,'deps/fakemodem/bin','fakenet'),
|
||
|
stdout=subprocess.PIPE)
|
||
|
return self.fakenet_process.stdout.readline().rstrip()
|
||
|
|
||
|
|
||
|
def _start_fake_modem(self, patternfiles):
|
||
|
"""Start the fakemodem program and return the pty path to access it
|
||
|
|
||
|
Start up the fakemodem program
|
||
|
Argument:
|
||
|
patternfiles -- List of files to read for command/response patterns
|
||
|
|
||
|
Returns the device path of the pty that serves the fake modem, e.g.
|
||
|
/dev/pts/4.
|
||
|
Sets self.fakemodem_process as a handle to the process, and
|
||
|
self.fakemodem as a DBus interface to it.
|
||
|
"""
|
||
|
scriptargs = ["--patternfile=" + x for x in patternfiles]
|
||
|
name = os.path.join(self.autodir, 'deps/fakemodem/bin', 'fakemodem')
|
||
|
self.fakemodem_process = subprocess.Popen(
|
||
|
[os.path.join(self.autodir, 'deps/fakemodem/bin', 'fakemodem')]
|
||
|
+ scriptargs,
|
||
|
stdout=subprocess.PIPE)
|
||
|
ptyname = self.fakemodem_process.stdout.readline().rstrip()
|
||
|
time.sleep(2) # XXX
|
||
|
self.fakemodem = dbus.Interface(
|
||
|
dbus.SystemBus().get_object('org.chromium.FakeModem', '/'),
|
||
|
'org.chromium.FakeModem')
|
||
|
return ptyname
|
||
|
|
||
|
|
||
|
def _start_modemmanager(self, netname, modemname):
|
||
|
"""Start modemmanager under the control of fake devices.
|
||
|
|
||
|
Arguments:
|
||
|
netname -- fake network interface name (e.g. tun0)
|
||
|
modemname -- path to pty node device of fake modem (e.g. /dev/pts/4)
|
||
|
|
||
|
Returns...
|
||
|
|
||
|
"""
|
||
|
id_props = ['property_ID_MM_CANDIDATE=1',
|
||
|
'property_ID_VENDOR_ID=04e8', # Samsung USB VID
|
||
|
'property_ID_MODEL_ID=6872' # Y3300 modem PID
|
||
|
]
|
||
|
tty_device = (['device_file=%s' % (modemname),
|
||
|
'name=%s' % (modemname[5:]), # remove leading /dev/
|
||
|
'subsystem=tty',
|
||
|
'driver=fake',
|
||
|
'sysfs_path=/sys/devices/fake/tty',
|
||
|
'parent=/dev/fake-parent'] +
|
||
|
id_props)
|
||
|
net_device = (['device_file=/dev/fakenet',
|
||
|
'name=%s' % (netname),
|
||
|
'subsystem=net',
|
||
|
'driver=fake',
|
||
|
'sysfs_path=/sys/devices/fake/net',
|
||
|
'parent=/dev/fake-parent'] +
|
||
|
id_props)
|
||
|
parent_device=['device_file=/dev/fake-parent',
|
||
|
'sysfs_path=/sys/devices/fake/parent',
|
||
|
'devtype=usb_device',
|
||
|
'subsystem=usb']
|
||
|
environment = { 'FAKEGUDEV_DEVICES' : ':'.join(tty_device +
|
||
|
net_device +
|
||
|
parent_device),
|
||
|
'FAKEGUDEV_BLOCK_REAL' : 'true',
|
||
|
'G_DEBUG' : 'fatal_criticals',
|
||
|
'LD_PRELOAD' : os.path.join(self.autodir,
|
||
|
"deps/fakegudev/lib",
|
||
|
"libfakegudev.so") }
|
||
|
self.modemmanager = subprocess.Popen(['/usr/sbin/modem-manager',
|
||
|
'--debug',
|
||
|
'--log-level=DEBUG',
|
||
|
'--log-file=/tmp/mm-log'],
|
||
|
env=environment)
|
||
|
time.sleep(3) # wait for DeviceAdded signal?
|
||
|
self.modemmanager.poll()
|
||
|
if self.modemmanager.returncode is not None:
|
||
|
self.modemmanager = None
|
||
|
raise error.TestFail("ModemManager quit early")
|
||
|
|
||
|
# wait for MM to stabilize?
|
||
|
return modem.ModemManager(provider='org.freedesktop')
|
||
|
|
||
|
def _stop_fake_network(self):
|
||
|
if self.fakenet_process:
|
||
|
self.fakenet_process.poll()
|
||
|
if self.fakenet_process.returncode is None:
|
||
|
self.fakenet_process.terminate()
|
||
|
self.fakenet_process.wait()
|
||
|
|
||
|
def _stop_fake_modem(self):
|
||
|
if self.fakemodem_process:
|
||
|
self.fakemodem_process.poll()
|
||
|
if self.fakemodem_process.returncode is None:
|
||
|
self.fakemodem_process.terminate()
|
||
|
self.fakemodem_process.wait()
|
||
|
|
||
|
def _stop_modemmanager(self):
|
||
|
if self.modemmanager:
|
||
|
self.modemmanager.poll()
|
||
|
if self.modemmanager.returncode is None:
|
||
|
self.modemmanager.terminate()
|
||
|
self.modemmanager.wait()
|
||
|
|
||
|
|
||
|
def __enter__(self):
|
||
|
fakenetname = self._start_fake_network()
|
||
|
fakemodemname = self._start_fake_modem(self.modem_pattern_files)
|
||
|
self.mm = self._start_modemmanager(fakenetname, fakemodemname)
|
||
|
# This would be better handled by listening for DeviceAdded, but
|
||
|
# since we've blocked everything else and only supplied data for
|
||
|
# one modem, it's going to be right
|
||
|
self.modem_object_path = self.mm.path + '/Modems/0'
|
||
|
return self
|
||
|
|
||
|
def __exit__(self, exception, value, traceback):
|
||
|
self._stop_modemmanager()
|
||
|
self._stop_fake_modem()
|
||
|
self._stop_fake_network()
|
||
|
return False
|