blob: 9bfc81bcc4662e53a7290a6db64272714a98237f [file] [log] [blame]
# Copyright 2015 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.
"""Unittests for the debug_link.py module."""
from __future__ import print_function
import mock
from chromite.lib import cros_build_lib_unittest
from chromite.lib import cros_test_lib
from chromite.lib import debug_link
from chromite.lib import partial_mock
# pylint: disable=protected-access
class NetworkInterfaceTest(cros_build_lib_unittest.RunCommandTestCase):
"""Tests for NetworkInterface."""
def testDevicePropertiesParse(self):
"""Test for correct parsing of udevadm results in GetDeviceProperties()."""
self.rc.AddCmdResult(
partial_mock.In('udevadm'),
output='%s=1111\n%s=2222\nignore=value' %
(debug_link._PROPERTY_VENDOR_ID, debug_link._PROPERTY_PRODUCT_ID))
results = debug_link.NetworkInterface('').GetDeviceProperties()
self.assertEqual(results[debug_link._PROPERTY_VENDOR_ID], '1111')
self.assertEqual(results[debug_link._PROPERTY_PRODUCT_ID], '2222')
self.assertEqual(results.get('ignore'), None)
class NetworkInterfaceMock(partial_mock.PartialMock):
"""Mocks debug_link.NetworkInterface."""
TARGET = 'chromite.lib.debug_link.NetworkInterface'
ATTRS = ('BringDown', 'BringUp', 'Rename')
def BringDown(self, _inst):
pass
def BringUp(self, _inst, *_args):
pass
def Rename(self, _inst, *_args):
pass
class ConfigureDebugLinkRenameTest(cros_test_lib.MockTestCase):
"""Tests for _ConfigureDebugLink() interface renaming."""
def setUp(self):
self.StartPatcher(NetworkInterfaceMock())
def testCollision(self):
"""Test that rename collisions are handled."""
def _RenameSideEffect(new_ifname):
if new_ifname == 'veth0':
raise debug_link.InterfaceNameExistsError()
interface = debug_link.NetworkInterface('eth0')
self.PatchObject(interface, 'Rename', side_effect=_RenameSideEffect)
debug_link._ConfigureDebugLink(interface)
interface.Rename.assert_has_calls([mock.call('veth0'), mock.call('veth1')])
def testExhaustNames(self):
"""Test to make sure exception is thrown if all veth* names are in use."""
interface = debug_link.NetworkInterface('eth0')
self.PatchObject(
interface, 'Rename', side_effect=debug_link.InterfaceNameExistsError())
self.assertRaises(debug_link.DebugLinkInitializationFailedError,
debug_link._ConfigureDebugLink, (interface))
class InitializeDebugLinkTest(cros_test_lib.MockTestCase):
"""Tests for InitializeDebugLink()."""
def setUp(self):
self.StartPatcher(NetworkInterfaceMock())
def _MockNetworkDevices(self, devices_info):
"""Mocks the environment to return the specified device information.
Args:
devices_info: List of device information to return. Each entry is a
tuple: (ifname, properties, is_up, has_ip).
Returns:
Dictionary of mock NetworkInterface objects with |ifname| as keys.
"""
interfaces = {}
for ifname, props, is_up, has_ip in devices_info:
interface = debug_link.NetworkInterface(ifname)
self.PatchObject(interface, 'GetDeviceProperties', return_value=props)
self.PatchObject(interface, 'IsUp', return_value=is_up)
self.PatchObject(interface, 'HasIPAddress', return_value=has_ip)
interfaces[ifname] = interface
self.PatchObject(
debug_link.NetworkInterface, 'GetInterfaces',
return_value=[interface for _, interface in interfaces.iteritems()])
return interfaces
def testOneDebugLinkUnconfigured(self):
"""Test initializing one unconfigured Debug Link."""
# Mock out one uninteresting device and one interesting device that is
# not configured.
interfaces = self._MockNetworkDevices([
('eth0', {'prop': 'not-important'}, True, True),
('eth1', {debug_link._PROPERTY_PRODUCT_ID: debug_link._PRODUCT_ID,
debug_link._PROPERTY_VENDOR_ID: debug_link._VENDOR_ID},
False, False)])
ip = debug_link.InitializeDebugLink()
self.assertEqual(ip, debug_link._HOST_IP)
intf = interfaces['eth1']
intf.BringDown.assert_called_once_with(intf)
intf.Rename.assert_called_once_with(intf, 'veth0')
intf.BringUp.assert_called_once_with(intf, debug_link._HOST_IP)
def testOneDebugLinkAlreadyInitialized(self):
"""Test one Debug Link that is already initialized."""
# Mock out one interesting device that is already configured.
interfaces = self._MockNetworkDevices([
('veth0', {debug_link._PROPERTY_PRODUCT_ID: debug_link._PRODUCT_ID,
debug_link._PROPERTY_VENDOR_ID: debug_link._VENDOR_ID},
True, True)])
ip = debug_link.InitializeDebugLink()
self.assertEqual(ip, debug_link._HOST_IP)
intf = interfaces['veth0']
self.assertFalse(intf.BringDown.called)
self.assertFalse(intf.Rename.called)
def testNoDebugLink(self):
"""Test for exception raised when no Debug Link is found."""
# Mock out two uninteresting devices.
self._MockNetworkDevices([
('eth0', {'prop': 'not-important'}, True, True),
('eth1', {'prop': 'also-not-important'}, True, True)])
self.assertRaises(debug_link.DebugLinkMissingError,
debug_link.InitializeDebugLink)