"""wvmInstance.cached_reads(): inside the block the domain XML (per flags) and
the host capabilities are read from libvirt once; outside it every read goes
to libvirt, as code that changes the VM needs."""
import unittest
from django.conf import settings
if not settings.configured:
settings.configure(MAC_OUI="52:54:10")
from vrtManager.instance import wvmInstance
class FakeDomain:
def __init__(self):
self.reads = []
self.fail = False
def XMLDesc(self, flags):
if self.fail:
raise RuntimeError("libvirt error")
self.reads.append(flags)
return f""
class FakeConn:
def __init__(self):
self.caps = 0
self.defined = []
def getCapabilities(self):
self.caps += 1
return ""
def defineXML(self, xml):
self.defined.append(xml)
def proxy():
p = wvmInstance.__new__(wvmInstance) # no connection: only these calls
p.instance = FakeDomain()
p.wvm = FakeConn()
return p
class CachedReadsTestCase(unittest.TestCase):
def test_outside_the_block_every_read_goes_to_libvirt(self):
p = proxy()
p._XMLDesc(0)
p._XMLDesc(0)
p.get_cap_xml()
p.get_cap_xml()
self.assertEqual((p.instance.reads, p.wvm.caps), ([0, 0], 2))
def test_inside_the_block_each_flags_value_is_read_once(self):
p = proxy()
with p.cached_reads():
first = [p._XMLDesc(0), p._XMLDesc(1), p._XMLDesc(3)]
again = [p._XMLDesc(0), p._XMLDesc(1), p._XMLDesc(3)]
p.get_cap_xml()
p.get_cap_xml()
self.assertEqual(first, again)
self.assertEqual(p.instance.reads, [0, 1, 3])
self.assertEqual(p.wvm.caps, 1)
def test_the_block_ends_with_its_cache(self):
p = proxy()
with p.cached_reads():
p._XMLDesc(0)
with p.cached_reads():
p._XMLDesc(0)
p._XMLDesc(0)
self.assertEqual(p.instance.reads, [0, 0, 0])
def test_an_error_inside_the_block_still_ends_it(self):
p = proxy()
with self.assertRaises(ValueError), p.cached_reads():
p._XMLDesc(0)
raise ValueError
p._XMLDesc(0)
self.assertEqual(p.instance.reads, [0, 0])
def test_a_failed_read_is_not_cached(self):
p = proxy()
with p.cached_reads():
p.instance.fail = True
with self.assertRaises(RuntimeError):
p._XMLDesc(0)
p.instance.fail = False
p._XMLDesc(0)
self.assertEqual(p.instance.reads, [0])
def test_a_definition_change_drops_the_cache(self):
p = proxy()
with p.cached_reads():
p._XMLDesc(3)
p._defineXML("")
p._XMLDesc(3)
self.assertEqual(p.instance.reads, [3, 3])
def test_blocks_do_not_nest(self):
p = proxy()
with p.cached_reads(), self.assertRaises(RuntimeError), p.cached_reads():
pass
def test_two_proxies_do_not_share_a_cache(self):
a, b = proxy(), proxy()
with a.cached_reads():
a._XMLDesc(0)
b._XMLDesc(0)
b._XMLDesc(0)
self.assertEqual((a.instance.reads, b.instance.reads), ([0], [0, 0]))