<filename>vanir/tests/vm/init.py
import lxml.etree

import vanir
import vanir.events
import vanir.vm

import vanir.tests

class TestVMM(object):
    def __init__(self):
        super(TestVMM, self).__init__()
        self.offline_mode = True


class TestApp(object):
    def __init__(self):
        super(TestApp, self).__init__()
        self.domains = {}
        self.vmm = TestVMM()


class TestVM(vanir.vm.BaseVM):
    qid = vanir.property('qid', type=int)
    name = vanir.property('name')
    testprop = vanir.property('testprop')
    testlabel = vanir.property('testlabel')
    defaultprop = vanir.property('defaultprop', default='defaultvalue')

class TC_10_BaseVM(vanir.tests.VanirTestCase):
    def setUp(self):
        super().setUp()
        self.xml = lxml.etree.XML('''
<vanir version="3"> <!-- xmlns="https://vanir-os.org/VOSXML/1" -->
    <labels>
        <label id="label-1" color="#cc0000">red</label>
    </labels>

    <domains>
        <domain id="domain-1" class="TestVM">
            <properties>
                <property name="qid">1</property>
                <property name="name">domain1</property>
                <property name="testprop">testvalue</property>
                <property name="testlabel" ref="label-1" />
            </properties>

            <tags>
                <tag name="testtag"/>
            </tags>

            <features>
                <feature name="testfeature_empty"></feature>
                <feature name="testfeature_aqq">aqq</feature>
            </features>

            <devices class="pci">
                <device backend-domain="domain1" id="00_11.22">
                  <option name="no-strict-reset">True</option>
                </device>
            </devices>

            <devices class="usb" />
            <devices class="audio-in" />
            <devices class="firewire" />
            <devices class="i2c" />
            <devices class="isa" />
        </domain>
    </domains>
</vanir>
        ''')

    def test_000_load(self):
        node = self.xml.xpath('//domain')[0]
        vm = TestVM(TestApp(), node)
        vm.app.domains['domain1'] = vm
        vm.load_properties(load_stage=None)
        vm.load_extras()

        self.assertEqual(vm.qid, 1)
        self.assertEqual(vm.testprop, 'testvalue')
        self.assertEqual(vm.testprop, 'testvalue')
        self.assertEqual(vm.testlabel, 'label-1')
        self.assertEqual(vm.defaultprop, 'defaultvalue')
        self.assertEqual(vm.tags, {'testtag'})
        self.assertEqual(vm.features, {
            'testfeature_empty': '',
            'testfeature_aqq': 'aqq',
        })

        self.assertCountEqual(vm.devices.keys(), ('pci',))
        self.assertCountEqual(list(vm.devices['pci'].persistent()),
            [vanir.ext.pci.PCIDevice(vm, '00_11.22')])

        assignments = list(vm.devices['pci'].assignments())
        self.assertEqual(len(assignments), 1)
        self.assertEqual(assignments[0].options, {'no-strict-reset': 'True'})
        self.assertEqual(assignments[0].persistent, True)

        self.assertXMLIsValid(vm.__xml__(), 'domain.rng')

    def test_001_nxproperty(self):
        xml = lxml.etree.XML('''
<vanir version="3">
    <domains>
        <domain id="domain-1" class="TestVM">
            <properties>
                <property name="qid">1</property>
                <property name="name">domain1</property>
                <property name="nxproperty">nxvalue</property>
            </properties>
        </domain>
    </domains>
</vanir>
        ''')

        node = xml.xpath('//domain')[0]

        with self.assertRaises(TypeError):
            TestVM(None, node)

    def test_002_save_nxproperty(self):
        vm = TestVM(None, None, qid=1, name='testvm')
        vm.nxproperty = 'value'
        xml = vm.__xml__()
        self.assertNotIn('nxproperty', xml)


class TC_20_Tags(vanir.tests.VanirTestCase):
    def setUp(self):
        super(TC_20_Tags, self).setUp()
        self.vm = vanir.tests.TestEmitter()
        self.tags = vanir.vm.Tags(self.vm)

    def test_000_add(self):
        self.tags.add('testtag')
        self.assertEventFired(self.vm, 'domain-tag-add:testtag',
            kwargs={'tag': 'testtag'})

    def test_001_add_existing(self):
        self.tags.add('testtag')
        self.vm.fired_events.clear()
        self.tags.add('testtag')
        self.assertEventNotFired(self.vm, 'domain-tag-add:testtag')

    def test_002_remove(self):
        self.tags.add('testtag')
        self.vm.fired_events.clear()
        self.tags.remove('testtag')
        self.assertEventFired(self.vm, 'domain-tag-delete:testtag',
            kwargs={'tag': 'testtag'})

    def test_003_remove_not_present(self):
        with self.assertRaises(KeyError):
            self.tags.remove('testtag')
        self.assertEventNotFired(self.vm, 'domain-tag-delete:testtag')

    def test_004_discard_not_present(self):
        with self.assertNotRaises(KeyError):
            self.tags.discard('testtag')
        self.assertEventNotFired(self.vm, 'domain-tag-delete:testtag')

    def test_005_discard_present(self):
        self.tags.add('testtag')
        with self.assertNotRaises(KeyError):
            self.tags.discard('testtag')
        self.assertEventFired(self.vm, 'domain-tag-delete:testtag',
            kwargs={'tag': 'testtag'})

    def test_006_clear(self):
        self.tags.add('testtag')
        self.tags.add('testtag2')
        self.vm.fired_events.clear()
        self.tags.clear()
        self.assertEventFired(self.vm, 'domain-tag-delete:testtag',
            kwargs={'tag': 'testtag'})
        self.assertEventFired(self.vm, 'domain-tag-delete:testtag2',
            kwargs={'tag': 'testtag2'})

    def test_007_update(self):
        self.tags.add('testtag')
        self.tags.add('testtag2')
        self.vm.fired_events.clear()
        self.tags.update(('testtag2', 'testtag3'))
        self.assertEventFired(self.vm, 'domain-tag-add:testtag3',
            kwargs={'tag': 'testtag3'})
        self.assertEventNotFired(self.vm, 'domain-tag-add:testtag2',
            kwargs={'tag': 'testtag2'})


class TC_21_Features(vanir.tests.VanirTestCase):
    def setUp(self):
        super(TC_21_Features, self).setUp()
        self.vm = vanir.tests.TestEmitter()
        self.features = vanir.features.Features(self.vm)

    def test_000_set(self):
        self.features['testfeature'] = 'value'
        self.assertEventFired(self.vm, 'domain-feature-set:testfeature',
            kwargs={'feature': 'testfeature', 'value': 'value'})

    def test_001_set_existing(self):
        self.features['test'] = 'oldvalue'
        self.vm.fired_events.clear()
        self.features['test'] = 'value'
        self.assertEventFired(self.vm, 'domain-feature-set:test',
            kwargs={'feature': 'test', 'value': 'value', 'oldvalue':
                'oldvalue'})

    def test_002_unset(self):
        self.features['test'] = 'value'
        self.vm.fired_events.clear()
        del self.features['test']
        self.assertEventFired(self.vm, 'domain-feature-delete:test',
            kwargs={'feature': 'test'})

    def test_003_unset_not_present(self):
        with self.assertRaises(KeyError):
            del self.features['test']
        self.assertEventNotFired(self.vm, 'domain-feature-delete')
        self.assertEventNotFired(self.vm, 'domain-feature-delete:test')

    def test_004_set_bool_true(self):
        self.features['test'] = True
        self.assertTrue(self.features['test'])
        self.assertEventFired(self.vm, 'domain-feature-set:test',
            kwargs={'feature': 'test', 'value': '1'})

    def test_005_set_bool_false(self):
        self.features['test'] = False
        self.assertFalse(self.features['test'])
        self.assertEventFired(self.vm, 'domain-feature-set:test',
            kwargs={'feature': 'test', 'value': ''})

    def test_006_set_int(self):
        self.features['test'] = 123
        self.assertEventFired(self.vm, 'domain-feature-set:test',
            kwargs={'feature': 'test', 'value': '123'})

    def test_007_clear(self):
        self.features['test'] = 'value1'
        self.features['test2'] = 'value2'
        self.vm.fired_events.clear()
        self.features.clear()
        self.assertEventFired(self.vm, 'domain-feature-delete:test',
            kwargs={'feature': 'test'})
        self.assertEventFired(self.vm, 'domain-feature-delete:test2',
            kwargs={'feature': 'test2'})

    def test_008_update(self):
        self.features['test'] = 'value'
        self.features['test2'] = 'value2'
        self.vm.fired_events.clear()
        self.features.update({'test2': 'value3', 'test3': 'value4'})
        self.assertEqual(self.features['test2'], 'value3')
        self.assertEqual(self.features['test3'], 'value4')
        self.assertEqual(self.features['test'], 'value')
        self.assertEventFired(self.vm, 'domain-feature-set:test2',
            kwargs={'feature': 'test2', 'value': 'value3',
                'oldvalue': 'value2'})
        self.assertEventFired(self.vm, 'domain-feature-set:test3',
            kwargs={'feature': 'test3', 'value': 'value4'})
