tests: Add XML editing UI tests

This commit is contained in:
Cole Robinson 2019-05-23 16:14:39 -04:00
parent a5f4033493
commit 2a1cf411dd
10 changed files with 401 additions and 29 deletions

View File

@ -623,9 +623,9 @@ class AddHardware(uiutils.UITestCase):
uiutils.check_in_loop(lambda: details.active)
def testAddCornerCases(self):
def testAddHWCornerCases(self):
"""
Could random addhardware related tests
Random addhardware related tests
"""
details = self._open_details_window("test-many-devices")
addhw = self._open_addhw_window(details)
@ -645,6 +645,7 @@ class AddHardware(uiutils.UITestCase):
alert.find("No", "push button").click()
uiutils.check_in_loop(lambda: details.active)
# Test live adding, error dialog, click yes
self._open_addhw_window(details)
finish.click()
alert = self.app.root.find("vmm dialog", "alert")
@ -654,3 +655,51 @@ class AddHardware(uiutils.UITestCase):
alert.find("Details", "toggle button").click_expander()
alert.find("Yes", "push button").click()
uiutils.check_in_loop(lambda: alert.dead)
def testAddHWXMLEdit(self):
"""
Test XML editor integration
"""
details = self._open_details_window()
win = self._open_addhw_window(details)
finish = win.find("Finish", "push button")
# Disk test, change path and make sure we error it is missing
win.find("XML", "page tab").click()
xmleditor = win.find("XML editor")
origpath = "/var/lib/libvirt/images/test-clone-simple.qcow2"
newpath = "/FOO/XMLEDIT/test1.img"
xmleditor.text = xmleditor.text.replace(origpath, newpath)
finish.click()
alert = self.app.root.find("vmm dialog", "alert")
alert.find_fuzzy("non-existent path")
alert.find("Close", "push button").click()
# Undo the bad change, change bus/target
xmleditor.text = xmleditor.text.replace(newpath, origpath)
xmleditor.text = xmleditor.text.replace("hdb", "xvda")
xmleditor.text = xmleditor.text.replace("ide", "xen")
finish.click()
# Verify the changes applied
details.find("Xen Disk 1").click()
uiutils.check_in_loop(lambda: details.active)
win = self._open_addhw_window(details)
tab = self._select_hw(win, "Storage", "storage-tab")
tab.find_fuzzy("Select or create", "radio").click()
tab.find("storage-browse", "push button").click()
browse = self.app.root.find("Choose Storage Volume", "frame")
browse.find(os.path.basename(origpath))
browse.find("Cancel").click()
# Select XML, switch to new dev type, verify we change focus
win.find("XML", "page tab").click()
xmleditor = win.find("XML editor")
uiutils.check_in_loop(lambda: xmleditor.showing)
tab = self._select_hw(win, "Network", "network-tab")
uiutils.check_in_loop(lambda: not xmleditor.showing)
# Do standard xmleditor tests
self._test_xmleditor_interactions(win, finish)
win.find("Cancel", "push button").click()
uiutils.check_in_loop(lambda: not win.visible)

View File

@ -9,21 +9,26 @@ class CreateNet(uiutils.UITestCase):
UI tests for the createnet wizard
"""
def _open_create_win(self, hostwin):
hostwin.find("net-add", "push button").click()
win = self.app.root.find(
"Create a new virtual network", "frame")
return win
##############
# Test cases #
##############
def testCreateNet(self):
# Open the createnet dialog
hostwin = self._open_host_window("Virtual Networks")
hostwin.find("net-add", "push button").click()
win = self.app.root.find(
"Create a new virtual network", "frame")
win = self._open_create_win(hostwin)
# Create a simple default network
newname = "a-test-new-net"
finish = win.find("Finish", "push button")
name = win.find("Name:", "text")
finish = win.find("Finish", "push button")
self.assertEqual(name.text, "network")
newname = "a-test-new-net"
name.text = newname
finish.click()
@ -52,6 +57,32 @@ class CreateNet(uiutils.UITestCase):
# Ensure it's gone
uiutils.check_in_loop(lambda: cell.dead)
def testCreateNetXMLEditor(self):
hostwin = self._open_host_window("Virtual Networks")
win = self._open_create_win(hostwin)
name = win.find("Name:", "text")
finish = win.find("Finish", "push button")
# Create a new obj with XML edited name, verify it worked
tmpname = "objtmpname"
newname = "froofroo"
name.text = tmpname
win.find("XML", "page tab").click()
xmleditor = win.find("XML editor")
xmleditor.text = xmleditor.text.replace(
">%s<" % tmpname, ">%s<" % newname)
finish.click()
uiutils.check_in_loop(lambda: hostwin.active)
cell = hostwin.find(newname, "table cell")
cell.click()
# Do standard xmleditor tests
win = self._open_create_win(hostwin)
self._test_xmleditor_interactions(win, finish)
win.find("Cancel", "push button").click()
uiutils.check_in_loop(lambda: not win.visible)
# Ensure host window closes fine
hostwin.click()
hostwin.keyCombo("<ctrl>w")

View File

@ -9,21 +9,27 @@ class CreatePool(uiutils.UITestCase):
UI tests for the createpool wizard
"""
def _open_create_win(self, hostwin):
hostwin.find("pool-add", "push button").click()
win = self.app.root.find(
"Add a New Storage Pool", "frame")
uiutils.check_in_loop(lambda: win.active)
return win
##############
# Test cases #
##############
def testCreatePool(self):
# Open the createnet dialog
hostwin = self._open_host_window("Storage")
hostwin.find("pool-add", "push button").click()
win = self.app.root.find(
"Add a New Storage Pool", "frame")
win = self._open_create_win(hostwin)
# Create a simple default dir pool
newname = "a-test-new-pool"
finish = win.find("Finish", "push button")
name = win.find("Name:", "text")
self.assertEqual(name.text, "pool")
newname = "a-test-new-pool"
name.text = newname
finish.click()
@ -52,10 +58,8 @@ class CreatePool(uiutils.UITestCase):
# Ensure it's gone
uiutils.check_in_loop(lambda: cell.dead)
# Test a scsi pool
hostwin.find("pool-add", "push button").click()
uiutils.check_in_loop(lambda: win.active)
win = self._open_create_win(hostwin)
typ = win.find("Type:", "combo box")
newname = "a-scsi-pool"
name.text = "a-scsi-pool"
@ -67,8 +71,7 @@ class CreatePool(uiutils.UITestCase):
hostwin.find(newname, "table cell")
# Test a ceph pool
hostwin.find("pool-add", "push button").click()
uiutils.check_in_loop(lambda: win.active)
win = self._open_create_win(hostwin)
newname = "a-ceph-pool"
name.text = "a-ceph-pool"
typ.click()
@ -83,3 +86,29 @@ class CreatePool(uiutils.UITestCase):
hostwin.keyCombo("<ctrl>w")
uiutils.check_in_loop(lambda: not hostwin.showing and
not hostwin.active)
def testCreatePoolXMLEditor(self):
hostwin = self._open_host_window("Storage")
win = self._open_create_win(hostwin)
finish = win.find("Finish", "push button")
name = win.find("Name:", "text")
# Create a new obj with XML edited name, verify it worked
tmpname = "objtmpname"
newname = "froofroo"
name.text = tmpname
win.find("XML", "page tab").click()
xmleditor = win.find("XML editor")
xmleditor.text = xmleditor.text.replace(
">%s<" % tmpname, ">%s<" % newname)
finish.click()
uiutils.check_in_loop(lambda: hostwin.active)
cell = hostwin.find(newname, "table cell")
cell.click()
# Do standard xmleditor tests
win = self._open_create_win(hostwin)
self._test_xmleditor_interactions(win, finish)
win.find("Cancel", "push button").click()
uiutils.check_in_loop(lambda: not win.visible)

View File

@ -9,23 +9,29 @@ class CreateVol(uiutils.UITestCase):
UI tests for the createvol wizard
"""
def _open_create_win(self, hostwin):
hostwin.find("vol-new", "push button").click()
win = self.app.root.find(
"Add a Storage Volume", "frame")
uiutils.check_in_loop(lambda: win.active)
return win
##############
# Test cases #
##############
def testCreateVol(self):
# Open the createnet dialog
hostwin = self._open_host_window("Storage")
poolcell = hostwin.find("default-pool", "table cell")
poolcell.click()
hostwin.find("vol-new", "push button").click()
win = self.app.root.find(
"Add a Storage Volume", "frame")
win = self._open_create_win(hostwin)
# Create a default qcow2 volume
newname = "a-newvol"
finish = win.find("Finish", "push button")
name = win.find("Name:", "text")
self.assertEqual(name.text, "vol")
newname = "a-newvol"
name.text = newname
win.find("Max Capacity:", "spin button").text = "10.5"
finish.click()
@ -43,8 +49,7 @@ class CreateVol(uiutils.UITestCase):
# Create a raw volume too
hostwin.find("vol-new", "push button").click()
uiutils.check_in_loop(lambda: win.active)
win = self._open_create_win(hostwin)
newname = "a-newvol.raw"
name.text = newname
combo = win.find("Format:", "combo box")
@ -58,3 +63,31 @@ class CreateVol(uiutils.UITestCase):
hostwin.keyCombo("<ctrl>w")
uiutils.check_in_loop(lambda: not hostwin.showing and
not hostwin.active)
def testCreateVolXMLEditor(self):
hostwin = self._open_host_window("Storage")
poolcell = hostwin.find("default-pool", "table cell")
poolcell.click()
win = self._open_create_win(hostwin)
finish = win.find("Finish", "push button")
name = win.find("Name:", "text")
vollist = hostwin.find("vol-list", "table")
# Create a new obj with XML edited name, verify it worked
tmpname = "objtmpname"
newname = "aafroofroo"
name.text = tmpname
win.find("XML", "page tab").click()
xmleditor = win.find("XML editor")
xmleditor.text = xmleditor.text.replace(
">%s.qcow2<" % tmpname, ">%s<" % newname)
finish.click()
uiutils.check_in_loop(lambda: hostwin.active)
vollist.find(newname)
# Do standard xmleditor tests
win = self._open_create_win(hostwin)
self._test_xmleditor_interactions(win, finish)
win.find("Cancel", "push button").click()
uiutils.check_in_loop(lambda: not win.visible)

View File

@ -46,6 +46,10 @@ class Details(uiutils.UITestCase):
lst = win.find("hw-list", "table")
self._walkUIList(win, lst, lambda: False)
# Select XML editor, and reverse walk the list
win.find("XML", "page tab").click()
self._walkUIList(win, lst, lambda: False, reverse=True)
def _testRename(self, origname, newname):
win = self._open_details_window(origname)
@ -465,7 +469,6 @@ class Details(uiutils.UITestCase):
tab = self._select_hw(win, "IDE Disk 1", "disk-tab")
self.assertTrue(share.checked)
# VM State change doesn't refresh UI
share.click()
self._start_vm(win)
@ -479,3 +482,33 @@ class Details(uiutils.UITestCase):
self.assertTrue(share.checked)
self._stop_vm(win)
self.assertTrue(not share.checked)
def testDetailsXMLEdit(self):
"""
Test XML editing interaction
"""
win = self._open_details_window(vmname="test-clone-simple")
finish = win.find("config-apply")
xmleditor = win.find("XML editor")
# Edit vcpu count and verify it's reflected in CPU page
tab = self._select_hw(win, "CPUs", "cpu-tab")
win.find("XML", "page tab").click()
xmleditor.text = xmleditor.text.replace(">5</vcpu", ">8</vcpu")
finish.click()
win.find("Details", "page tab").click()
self.assertEqual(
tab.find("Current allocation:", "spin button").text, "8")
# Make some disk edits
tab = self._select_hw(win, "IDE Disk 1", "disk-tab")
win.find("XML", "page tab").click()
origpath = "/dev/default-pool/test-clone-simple.img"
newpath = "/path/FOOBAR"
xmleditor.text = xmleditor.text.replace(origpath, newpath)
finish.click()
win.find("Details", "page tab").click()
self.assertTrue(win.find("disk-source-path").text, newpath)
# Do standard xmleditor tests
self._test_xmleditor_interactions(win, finish)

View File

@ -22,6 +22,36 @@ class Host(uiutils.UITestCase):
errlabel = win.find("net-error-label", "label")
self._walkUIList(win, lst, lambda: errlabel.showing)
# Select XML editor, and reverse walk the list
win.find("network-grid").find("XML", "page tab").click()
self._walkUIList(win, lst, lambda: errlabel.showing, reverse=True)
def testHostNetworkEdit(self):
"""
Test edits to net config
"""
win = self._open_host_window("Virtual Networks").find("network-grid")
finish = win.find("Apply", "push button")
# Shut off a pool, do an XML edit, verify it
win.find("default", "table cell").click()
delete = win.find("net-delete", "push button")
stop = win.find("net-stop", "push button")
stop.click()
uiutils.check_in_loop(lambda: delete.sensitive)
win.find("XML", "page tab").click()
xmleditor = win.find("XML editor")
origdev = "virbr0"
newdev = "virbr77"
xmleditor.text = xmleditor.text.replace(origdev, newdev)
finish.click()
win.find("Details", "page tab").click()
self.assertEqual(win.find("net-device").text, newdev)
# Do standard xmleditor tests
self._test_xmleditor_interactions(win, finish)
def testHostStorageSmokeTest(self):
"""
Verify that each storage pool displays, without error.
@ -30,3 +60,32 @@ class Host(uiutils.UITestCase):
lst = win.find("pool-list", "table")
errlabel = win.find("pool-error-label", "label")
self._walkUIList(win, lst, lambda: errlabel.showing)
# Select XML editor, and reverse walk the list
win.find("storage-grid").find("XML", "page tab").click()
self._walkUIList(win, lst, lambda: errlabel.showing, reverse=True)
def testHostStorageEdit(self):
"""
Test edits to pool config
"""
win = self._open_host_window("Storage").find("storage-grid")
finish = win.find("Apply", "push button")
# Shut off a pool, do an XML edit, verify it
win.find("default-pool", "table cell").click()
delete = win.find("pool-delete", "push button")
stop = win.find("pool-stop", "push button")
stop.click()
uiutils.check_in_loop(lambda: delete.sensitive)
win.find("XML", "page tab").click()
xmleditor = win.find("XML editor")
origpath = "/dev/default-pool"
newpath = "/dev/foo/bar/baz"
xmleditor.text = xmleditor.text.replace(origpath, newpath)
finish.click()
win.find("Details", "page tab").click()
self.assertEqual(win.find("pool-location").text, newpath)
# Do standard xmleditor tests
self._test_xmleditor_interactions(win, finish)

View File

@ -426,3 +426,87 @@ class NewVM(uiutils.UITestCase):
self.forward(newvm)
self.forward(newvm)
newvm.find_fuzzy("Finish", "button").click()
def testNewVMCustomizeXMLEdit(self):
"""
Test new VM with raw XML editing via customize wizard
"""
newvm = self._open_create_wizard()
# Create a custom named VM, using CDROM media, and default storage
vmname = "fooxmleditvm"
newvm.find_fuzzy("Local install media", "radio").click()
newvm.find_fuzzy("Forward", "button").click()
existpath = "/dev/default-pool/testvol1.img"
newvm.find("media-entry").text = existpath
uiutils.check_in_loop(
lambda: newvm.find("oslist-entry").text == "None detected")
newvm.find_fuzzy("Automatically detect", "check").click()
newvm.find("oslist-entry").text = "generic"
newvm.find("oslist-popover").find_fuzzy("generic").click()
newvm.find_fuzzy("Forward", "button").click()
newvm.find_fuzzy("Forward", "button").click()
newvm.find_fuzzy("Forward", "button").click()
newvm.find_fuzzy("Customize", "check").click()
newvm.find_fuzzy("Name", "text").text = vmname
newvm.find_fuzzy("Finish", "button").click()
# Change a VM setting and verify it
win = self.app.root.find_fuzzy("%s on" % vmname, "frame")
xmleditor = win.find("XML editor")
finish = win.find("config-apply")
win.find_fuzzy("Boot", "table cell").click()
tab = win.find("boot-tab")
self.assertEqual(
tab.find("Enable boot menu", "check box").checked, False)
win.find("XML", "page tab").click()
xmleditor.text = xmleditor.text.replace(
"<os>", "<os><bootmenu enable='yes'/>")
finish.click()
win.find("Details", "page tab").click()
self.assertEqual(
tab.find("Enable boot menu", "check box").checked, True)
# Change a device setting with the XML editor
win.find_fuzzy("NIC", "table cell").click()
tab = win.find("network-tab")
win.find("XML", "page tab").click()
oldbrname = "brplain"
newbrname = "BRFAKE"
xmleditor.text = xmleditor.text.replace(oldbrname, newbrname)
finish.click()
# Finish install.
win.find_fuzzy("Begin Installation", "button").click()
uiutils.check_in_loop(lambda: win.dead)
win = self.app.root.find_fuzzy("%s on" % vmname, "frame")
win.find("Details", "radio button").click()
# Verify VM change stuck
win.find_fuzzy("Boot", "table cell").click()
tab = win.find("boot-tab")
self.assertEqual(
tab.find("Enable boot menu", "check box").checked, True)
# Verify device change stuck
win.find_fuzzy("NIC", "table cell").click()
tab = win.find("network-tab")
self.assertEqual(
tab.find("Bridge name:", "text").text, newbrname)
# Verify install media is handled correctly after XML customize
win.find_fuzzy("IDE CDROM 1", "table cell").click()
tab = win.find("disk-tab")
self.assertEqual(tab.find("media-entry").text, existpath)
win.find("Shut Down", "push button").click()
run = win.find("Run", "push button")
uiutils.check_in_loop(lambda: run.sensitive)
self.assertEqual(tab.find("media-entry").text, "")
# Verify default disk storage was actually created. This has some
# special handling in domain.py
tab.find("Browse", "push button").click()
browsewin = self.app.root.find(
"Choose Storage Volume", "frame")
browsewin.find("%s.qcow2" % vmname, "table cell")

View File

@ -96,7 +96,7 @@ class UITestCase(unittest.TestCase):
check_in_loop(lambda: run.sensitive)
return win
def _walkUIList(self, win, lst, error_cb):
def _walkUIList(self, win, lst, error_cb, reverse=False):
"""
Toggle down through a UI list like addhardware, net/storage/iface
lists, and ensure an error isn't raised.
@ -104,6 +104,8 @@ class UITestCase(unittest.TestCase):
# Walk the lst UI and find all labelled table cells, these are
# the actual list entries
all_cells = lst.findChildren(lambda w: w.roleName == "table cell")
if reverse:
all_cells.reverse()
all_cells[0].click()
cells_per_selection = len([c for c in all_cells if c.focused])
@ -118,7 +120,7 @@ class UITestCase(unittest.TestCase):
continue
self.assertTrue(cell.state_selected)
dogtail.rawinput.pressKey("Down")
dogtail.rawinput.pressKey(reverse and "Up" or "Down")
if not win.active:
# Should mean an error dialog popped up
@ -134,6 +136,36 @@ class UITestCase(unittest.TestCase):
else:
self.assertTrue(not cell.state_selected)
def _test_xmleditor_interactions(self, win, finish):
"""
Helper to test some common XML editor interactions
"""
# Click the tab, make a bogus XML edit
win.find("XML", "page tab").click()
xmleditor = win.find("XML editor")
xmleditor.text = xmleditor.text.replace("<", "<FOO", 1)
# Trying to click away should warn that there's unapplied changes
win.find("Details", "page tab").click()
alert = self.app.root.find("vmm dialog")
alert.find_fuzzy("changes will be lost")
# Select 'No', meaning don't abandon changes
alert.find("No", "push button").click()
check_in_loop(lambda: xmleditor.showing)
# Click the finish button, but our bogus change should trigger error
finish.click()
alert = self.app.root.find("vmm dialog")
alert.find_fuzzy("(xmlParseDoc|tag mismatch)")
alert.find("Close", "push button").click()
# Try unapplied changes again, this time abandon our changes
win.find("Details", "page tab").click()
alert = self.app.root.find("vmm dialog")
alert.find("Yes", "push button").click()
check_in_loop(lambda: not xmleditor.showing)
class _FuzzyPredicate(dogtail.predicate.Predicate):
"""

View File

@ -3,6 +3,8 @@
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkBox" id="top-box">
<property name="width_request">400</property>
<property name="height_request">400</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">3</property>
@ -124,6 +126,11 @@
<property name="halign">start</property>
<property name="label">label</property>
<property name="selectable">True</property>
<child internal-child="accessible">
<object class="AtkObject" id="net-device-atkobject">
<property name="AtkObject::accessible-name">net-device</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>
@ -1061,5 +1068,10 @@
<property name="position">1</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="top-box-atkobject">
<property name="AtkObject::accessible-name">network-grid</property>
</object>
</child>
</object>
</interface>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.2 -->
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<object class="GtkImage" id="image3">
@ -344,6 +344,11 @@
<property name="halign">start</property>
<property name="label">label</property>
<property name="selectable">True</property>
<child internal-child="accessible">
<object class="AtkObject" id="pool-location-atkobject">
<property name="AtkObject::accessible-name">pool-location</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>
@ -655,5 +660,10 @@
<property name="top_attach">0</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="storage-grid-atkobject">
<property name="AtkObject::accessible-name">storage-grid</property>
</object>
</child>
</object>
</interface>