def test_qdev_functional(self):
        """ Test basic qdev workflow """
        qdev = self.create_qdev('vm1')

        # Add basic 'pc' devices
        out = qdev.insert(
            qdev.machine_by_params(ParamsDict({'machine_type': 'pc'})))
        assert isinstance(out, list)
        assert len(out) == 6, len(out)

        exp = r"""Devices of vm1:
machine
  aid = __0
  aobject = pci.0
  parent_bus = ()
  child_bus = \[.*QPCIBus.*, .*QStrictCustomBus.*\]
  params:
i440FX
  aid = __1
  aobject = None
  parent_bus = ({'aobject': 'pci.0'},)
  child_bus = \[\]
  params:
    driver = i440FX
    addr = 00
    bus = pci.0
PIIX4_PM
  aid = __2
  aobject = None
  parent_bus = ({'aobject': 'pci.0'},)
  child_bus = \[\]
  params:
    driver = PIIX4_PM
    addr = 01.3
    bus = pci.0
PIIX3
  aid = __3
  aobject = None
  parent_bus = ({'aobject': 'pci.0'},)
  child_bus = \[\]
  params:
    driver = PIIX3
    addr = 01
    bus = pci.0
piix3-ide
  aid = __4
  aobject = None
  parent_bus = ({'aobject': 'pci.0'},)
  child_bus = \[.*QIDEBus.*\]
  params:
    driver = piix3-ide
    addr = 01.1
    bus = pci.0
fdc
  aid = __5
  aobject = None
  parent_bus = \(\)
  child_bus = \[.*QFloppyBus.*\]
  params:"""
        out = qdev.str_long()
        self.assertNotEqual(
            re.findall(exp, out), None, 'Long representation is'
            'corrupted:\n%s\n%s' % (out, exp))

        exp = ("Buses of vm1\n"
               "  floppy(floppy): [None,None]\n"
               "  ide(ide): [None,None,None,None]\n"
               "  _PCI_CHASSIS_NR(None): {}\n"
               "  _PCI_CHASSIS(None): {}\n"
               "  pci.0(PCI): {0x0-0x0:t'i440FX',0x1-0x0:t'PIIX3',"
               "0x1-0x1:t'piix3-ide',0x1-0x3:t'PIIX4_PM'}")
        out = qdev.str_bus_short()
        assert out == exp, "Bus representation is ocrrupted:\n%s\n%s" % (out,
                                                                         exp)

        # Insert some good devices
        qdevice = qdevices.QDevice

        # Device with child bus
        bus = qbuses.QSparseBus('bus', [['addr'], [6]], 'hba1.0', 'hba',
                                'a_hba')
        dev = qdevice('HBA', {
            'id': 'hba1',
            'addr': 10
        },
                      parent_bus={'aobject': 'pci.0'},
                      child_bus=bus)
        out = qdev.insert(dev)
        assert isinstance(out, list), out
        assert len(out) == 1, len(out)

        # Device inside a child bus by type (most common)
        dev = qdevice('dev', {}, parent_bus={'type': 'hba'})
        out = qdev.insert(dev)
        assert isinstance(out, list), out
        assert len(out) == 1, len(out)

        # Device inside a child bus by autotest_id
        dev = qdevice('dev', {}, 'autotest_remove', {'aobject': 'a_hba'})
        out = qdev.insert(dev)
        assert isinstance(out, list), out
        assert len(out) == 1, len(out)

        # Device inside a child bus by busid
        dev = qdevice('dev', {}, 'autoremove', {'busid': 'hba1.0'})
        out = qdev.insert(dev)
        assert isinstance(out, list), out
        assert len(out) == 1, len(out)

        # Check the representation
        exp = ("Devices of vm1: [t'machine',t'i440FX',t'PIIX4_PM',t'PIIX3',"
               "t'piix3-ide',t'fdc',hba1,a'dev',a'dev',a'dev']")
        out = qdev.str_short()
        self.assertEqual(
            out, exp,
            "Short representation is corrupted:\n%s\n%s" % (out, exp))
        exp = ("Buses of vm1\n"
               "  hba1.0(hba): {0:a'dev',1:a'dev',2:a'dev'}\n"
               "  floppy(floppy): [None,None]\n"
               "  ide(ide): [None,None,None,None]\n"
               "  _PCI_CHASSIS_NR(None): {}\n"
               "  _PCI_CHASSIS(None): {}\n"
               "  pci.0(PCI): {0x0-0x0:t'i440FX',0x1-0x0:t'PIIX3',"
               "0x1-0x1:t'piix3-ide',0x1-0x3:t'PIIX4_PM',0xa-0x0:hba1}")
        out = qdev.str_bus_short()
        assert out == exp, 'Bus representation iscorrupted:\n%s\n%s' % (out,
                                                                        exp)

        # Check the representation
        exp = ("Devices of vm1: [t'machine',t'i440FX',t'PIIX4_PM',t'PIIX3',"
               "t'piix3-ide',t'fdc',hba1,a'dev',a'dev',a'dev']")
        out = qdev.str_short()
        assert out == exp, "Short representation is corrupted:\n%s\n%s" % (out,
                                                                           exp)
        exp = ("Buses of vm1\n"
               "  hba1.0(hba): {0:a'dev',1:a'dev',2:a'dev'}\n"
               "  floppy(floppy): [None,None]\n"
               "  ide(ide): [None,None,None,None]\n"
               "  _PCI_CHASSIS_NR(None): {}\n"
               "  _PCI_CHASSIS(None): {}\n"
               "  pci.0(PCI): {0x0-0x0:t'i440FX',0x1-0x0:t'PIIX3',"
               "0x1-0x1:t'piix3-ide',0x1-0x3:t'PIIX4_PM',0xa-0x0:hba1}")
        out = qdev.str_bus_short()
        assert out == exp, 'Bus representation is corrupted:\n%s\n%s' % (out,
                                                                         exp)

        # Now representation contains some devices, play with it a bit
        # length
        out = len(qdev)
        assert out == 10, "Length of qdev is incorrect: %s != %s" % (out, 10)

        # compare
        qdev2 = self.create_qdev('vm1')
        self.assertNotEqual(
            qdev, qdev2, "This qdev matches empty one:"
            "\n%s\n%s" % (qdev, qdev2))
        self.assertNotEqual(
            qdev2, qdev, "Empty qdev matches current one:"
            "\n%s\n%s" % (qdev, qdev2))
        for _ in xrange(10):
            qdev2.insert(qdevice())
        self.assertNotEqual(
            qdev, qdev2, "This qdev matches different one:"
            "\n%s\n%s" % (qdev, qdev2))
        self.assertNotEqual(
            qdev2, qdev,
            "Other qdev matches this one:\n%s\n%s" % (qdev, qdev2))
        # cmdline
        exp = (
            "-machine pc -device HBA,id=hba1,addr=0xa,bus=pci.0 -device dev "
            "-device dev -device dev")
        out = qdev.cmdline()
        self.assertEqual(
            out, exp, 'Corrupted qdev.cmdline() output:\n%s\n%s' % (out, exp))

        # get_by_qid (currently we have 2 devices of the same qid)
        out = qdev.get_by_qid('hba1')
        self.assertEqual(
            len(out), 1, 'Incorrect number of devices by qid '
            '"hba1": %s != 1\n%s' % (len(out), qdev.str_long()))

        # Remove some devices
        # Remove based on aid
        out = qdev.remove('__6')
        self.assertEqual(
            out, None, 'Failed to remove device:\n%s\nRepr:\n%s' %
            ('hba1__0', qdev.str_long()))

        # Remove device which contains other devices (without recursive)
        self.assertRaises(qcontainer.DeviceRemoveError, qdev.remove, 'hba1',
                          False)

        # Remove device which contains other devices (recursive)
        out = qdev.remove('hba1')
        self.assertEqual(
            out, None, 'Failed to remove device:\n%s\nRepr:\n%s' %
            ('hba1', qdev.str_long()))

        # Check the representation
        exp = ("Devices of vm1: [t'machine',t'i440FX',t'PIIX4_PM',t'PIIX3',"
               "t'piix3-ide',t'fdc']")
        out = qdev.str_short()
        assert out == exp, "Short representation is corrupted:\n%s\n%s" % (out,
                                                                           exp)
        exp = ("Buses of vm1\n"
               "  floppy(floppy): [None,None]\n"
               "  ide(ide): [None,None,None,None]\n"
               "  _PCI_CHASSIS_NR(None): {}\n"
               "  _PCI_CHASSIS(None): {}\n"
               "  pci.0(PCI): {0x0-0x0:t'i440FX',0x1-0x0:t'PIIX3',"
               "0x1-0x1:t'piix3-ide',0x1-0x3:t'PIIX4_PM'}")
        out = qdev.str_bus_short()
        assert out == exp, 'Bus representation is corrupted:\n%s\n%s' % (out,
                                                                         exp)
    def test_q_sparse_bus(self):
        """ Sparse bus tests (general bus testing) """
        bus = qbuses.QSparseBus('bus',
                                (['addr1', 'addr2', 'addr3'], [2, 6, 4]),
                                'my_bus', 'bus_type', 'autotest_bus')

        qdevice = qdevices.QDevice

        # Correct records
        params = {'addr1': '0', 'addr2': '0', 'addr3': '0', 'bus': 'my_bus'}
        dev = qdevice('dev1', params, parent_bus={'type': 'bus_type'})
        exp = []
        out = bus.insert(dev, False)
        self.assertEqual(
            out, exp, "Failed to add device; %s != %s\n%s\n\n%s" %
            (out, exp, dev.str_long(), bus.str_long()))

        params = {'addr1': '1', 'addr2': '0', 'addr3': '0', 'bus': 'my_bus'}
        dev = qdevice('dev2', params, parent_bus={'type': 'bus_type'})
        exp = []
        out = bus.insert(dev, False)
        self.assertEqual(
            out, exp, "Failed to add device; %s != %s\n%s\n\n%s" %
            (out, exp, dev.str_long(), bus.str_long()))

        params = {'addr1': '1', 'addr2': '1', 'addr3': '0', 'bus': 'my_bus'}
        dev = qdevice('dev3', params, parent_bus={'type': 'bus_type'})
        exp = []
        out = bus.insert(dev, False)
        self.assertEqual(
            out, exp, "Failed to add device; %s != %s\n%s\n\n%s" %
            (out, exp, dev.str_long(), bus.str_long()))

        params = {'addr1': '1', 'addr2': '1', 'addr3': '1', 'bus': 'my_bus'}
        dev = qdevice('dev4', params, parent_bus={'type': 'bus_type'})
        exp = []
        out = bus.insert(dev, False)
        self.assertEqual(
            out, exp, "Failed to add device; %s != %s\n%s\n\n%s" %
            (out, exp, dev.str_long(), bus.str_long()))

        params = {'addr1': '1', 'bus': 'my_bus'}
        dev = qdevice('dev5', params, parent_bus={'type': 'bus_type'})
        exp = []
        out = bus.insert(dev, False)
        self.assertEqual(
            out, exp, "Failed to add device; %s != %s\n%s\n\n%s" %
            (out, exp, dev.str_long(), bus.str_long()))

        params = {'bus': 'my_bus'}
        dev = qdevice('dev6', params, parent_bus={'type': 'bus_type'})
        exp = []
        out = bus.insert(dev, False)
        self.assertEqual(
            out, exp, "Failed to add device; %s != %s\n%s\n\n%s" %
            (out, exp, dev.str_long(), bus.str_long()))

        params = {}
        dev2 = qdevice('dev7', params, parent_bus={'type': 'bus_type'})
        exp = []
        out = bus.insert(dev2, False)
        self.assertEqual(
            out, exp, "Failed to add device; %s != %s\n%s\n\n%s" %
            (out, exp, dev2.str_long(), bus.str_long()))

        # Compare short repr
        exp = ("my_bus(bus_type): {0-0-0:a'dev1',0-0-1:a'dev6',0-0-2:a'dev7',"
               "1-0-0:a'dev2',1-0-1:a'dev5',1-1-0:a'dev3',1-1-1:a'dev4'}")
        out = str(bus.str_short())
        self.assertEqual(
            out, exp, "Short representation corrupted:\n%s\n%s"
            "\n\n%s" % (out, exp, bus.str_long()))

        # Incorrect records
        # Used address
        params = {'addr1': '0', 'addr2': '0', 'addr3': '0', 'bus': 'my_bus'}
        dev = qdevice('devI1', params, parent_bus={'type': 'bus_type'})
        exp = "UsedSlot"
        out = bus.insert(dev, False)
        self.assertEqual(
            out, exp, "Added bad device; %s != %s\n%s\n\n%s" %
            (out, exp, dev.str_long(), bus.str_long()))

        # Out of range address
        params = {'addr1': '0', 'addr2': '6', 'addr3': '0', 'bus': 'my_bus'}
        dev = qdevice('devI2', params, parent_bus={'type': 'bus_type'})
        exp = "BadAddr(False)"
        out = bus.insert(dev, False)
        self.assertEqual(
            out, exp, "Added bad device; %s != %s\n%s\n\n%s" %
            (out, exp, dev.str_long(), bus.str_long()))

        # Incorrect bus name
        params = {'bus': 'other_bus'}
        dev = qdevice('devI3', params, parent_bus={'type': 'bus_type'})
        exp = "BusId"
        out = bus.insert(dev, False)
        self.assertEqual(
            out, exp, "Added bad device; %s != %s\n%s\n\n%s" %
            (out, exp, dev.str_long(), bus.str_long()))

        # Compare short repr
        exp = ("my_bus(bus_type): {0-0-0:a'dev1',0-0-1:a'dev6',0-0-2:a'dev7',"
               "1-0-0:a'dev2',1-0-1:a'dev5',1-1-0:a'dev3',1-1-1:a'dev4'}")
        out = str(bus.str_short())
        self.assertEqual(
            out, exp, "Short representation corrupted:\n%s\n%s"
            "\n\n%s" % (out, exp, bus.str_long()))

        # Compare long repr
        exp = """Bus my_bus, type=bus_type
Slots:
---------------< 1-0-0 >---------------
  device
    aid = None
    aobject = None
    parent_bus = {'type': 'bus_type'}
    child_bus = []
    params:
      bus = my_bus
      addr2 = 0
      addr3 = 0
      addr1 = 1
      driver = dev2
---------------< 1-0-1 >---------------
  device
    aid = None
    aobject = None
    parent_bus = {'type': 'bus_type'}
    child_bus = []
    params:
      bus = my_bus
      addr1 = 1
      driver = dev5
---------------< 1-1-1 >---------------
  device
    aid = None
    aobject = None
    parent_bus = {'type': 'bus_type'}
    child_bus = []
    params:
      bus = my_bus
      addr2 = 1
      addr3 = 1
      addr1 = 1
      driver = dev4
---------------< 1-1-0 >---------------
  device
    aid = None
    aobject = None
    parent_bus = {'type': 'bus_type'}
    child_bus = []
    params:
      bus = my_bus
      addr2 = 1
      addr3 = 0
      addr1 = 1
      driver = dev3
---------------< 0-0-1 >---------------
  device
    aid = None
    aobject = None
    parent_bus = {'type': 'bus_type'}
    child_bus = []
    params:
      bus = my_bus
      driver = dev6
---------------< 0-0-0 >---------------
  device
    aid = None
    aobject = None
    parent_bus = {'type': 'bus_type'}
    child_bus = []
    params:
      bus = my_bus
      addr2 = 0
      addr3 = 0
      addr1 = 0
      driver = dev1
---------------< 0-0-2 >---------------
  device
    aid = None
    aobject = None
    parent_bus = {'type': 'bus_type'}
    child_bus = []
    params:
      driver = dev7
"""
        out = str(bus.str_long())
        self.assertEqual(
            out, exp,
            "Long representation corrupted:\n%s\n%s" % (repr(out), exp))

        # Low level functions
        # Get device by object
        exp = dev2
        out = bus.get(dev2)
        self.assertEqual(
            out, exp, "Failed to get device from bus:\n%s\n%s"
            "\n\n%s" % (out, exp, bus.str_long()))

        dev2.aid = 'bad_device3'
        exp = dev2
        out = bus.get('bad_device3')
        self.assertEqual(
            out, exp, "Failed to get device from bus:\n%s\n%s"
            "\n\n%s" % (out, exp, bus.str_long()))

        exp = None
        out = bus.get('missing_bad_device')
        self.assertEqual(
            out, exp, "Got device while expecting None:\n%s\n%s"
            "\n\n%s" % (out, exp, bus.str_long()))

        # Remove all devices
        devs = [dev for dev in bus]
        for dev in devs:
            bus.remove(dev)

        exp = 'Bus my_bus, type=bus_type\nSlots:\n'
        out = str(bus.str_long())
        self.assertEqual(out, exp,
                         "Long representation corrupted:\n%s\n%s" % (out, exp))