uitests: Add a bunch of addhardware testing

This commit is contained in:
Cole Robinson 2018-01-18 18:18:24 -05:00
parent 402b42b14a
commit 9232a51d55
5 changed files with 453 additions and 10 deletions

View File

@ -0,0 +1,317 @@
import tests
from tests.uitests import utils as uiutils
class Details(uiutils.UITestCase):
"""
UI tests for virt-manager's VM details window
"""
###################
# Private helpers #
###################
def _open_details_window(self, vmname="test-clone-simple"):
self.app.root.find_fuzzy(vmname, "table cell").click(button=3)
self.app.root.find_pattern("Open", "menu item").click()
win = self.app.root.find_pattern("%s on" % vmname, "frame")
win.find_pattern("Details", "radio button").click()
return win
def _open_addhw_window(self, details):
details.find_pattern("add-hardware", "push button").click()
addhw = self.app.root.find_pattern("Add New Virtual Hardware", "frame")
return addhw
def _select_hw(self, addhw, hwname, tabname):
addhw.find_pattern(hwname, "table cell").click()
tab = addhw.find_pattern(tabname, None)
uiutils.check_in_loop(lambda: tab.showing)
return tab
##############
# Test cases #
##############
def testAddGraphics(self):
"""
Graphics device testing
"""
details = self._open_details_window()
addhw = self._open_addhw_window(details)
finish = addhw.find_pattern("Finish", "push button")
# VNC example
tab = self._select_hw(addhw, "Graphics", "graphics-tab")
tab.find_pattern(None, "combo box", "Type:").click_combo_entry()
tab.find_fuzzy("VNC", "menu item").click()
tab.find_pattern(None, "combo box", "Listen type:").click_combo_entry()
tab.find_fuzzy("Address", "menu item").click()
tab.find_pattern(None, "combo box", "Address:").click_combo_entry()
tab.find_fuzzy("All interfaces", "menu item").click()
tab.find_pattern("graphics-port-auto", "check").click()
tab.find_pattern("graphics-port", "spin button").text = "1234"
tab.find_pattern(None, "check", "Password:").click()
passwd = tab.find_fuzzy("graphics-password", "text")
newpass = "foobar"
passwd.typeText(newpass)
tab.find_pattern("Show password", "check").click()
self.assertEqual(passwd.text, newpass)
tab.find_pattern(None, "combo box", "Keymap:").click()
self.pressKey("Down")
self.pressKey("Down")
self.pressKey("Down")
finish.click()
# Catch a port error
alert = self.app.root.find_pattern("vmm dialog", "alert")
alert.find_fuzzy("Port must be above 5900", "label")
alert.find_pattern("OK", "push button").click()
tab.find_pattern("graphics-port", "spin button").text = "5920"
uiutils.check_in_loop(lambda: details.active)
# Spice regular example
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Graphics", "graphics-tab")
tab.find_pattern(None, "combo box", "Type:").click_combo_entry()
tab.find_fuzzy("Spice", "menu item").click()
tab.find_pattern("graphics-tlsport-auto", "check").click()
tab.find_pattern("graphics-tlsport", "spin button").text = "5999"
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Spice GL example
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Graphics", "graphics-tab")
tab.find_pattern(None, "combo box", "Type:").click_combo_entry()
tab.find_fuzzy("Spice", "menu item").click()
tab.find_pattern(None, "combo box", "Listen type:").click_combo_entry()
tab.find_fuzzy("None", "menu item").click()
tab.find_pattern(None, "check box", "OpenGL:").click()
render = tab.find_pattern("graphics-rendernode", "combo box")
m = tab.find_fuzzy("Intel Corp", "menu item")
render.click_combo_entry()
self.assertTrue(m.selected)
self.pressKey("Escape")
finish.click()
uiutils.check_in_loop(lambda: details.active)
def testAddHosts(self):
"""
Add a few different USB and PCI devices
"""
details = self._open_details_window()
addhw = self._open_addhw_window(details)
finish = addhw.find_pattern("Finish", "push button")
# Add USB device dup1
tab = self._select_hw(addhw, "USB Host Device", "host-tab")
tab.find_fuzzy("HP Dup USB 1", "table cell").click()
finish.click()
alert = self.app.root.find_pattern("vmm dialog", "alert")
alert.find_fuzzy("device is already in use by", "label")
alert.find_pattern("Yes", "push button").click()
uiutils.check_in_loop(lambda: details.active)
# Add USB device dup2
self._open_addhw_window(details)
tab = self._select_hw(addhw, "USB Host Device", "host-tab")
tab.find_fuzzy("HP Dup USB 2", "table cell").click()
finish.click()
alert = self.app.root.find_pattern("vmm dialog", "alert")
alert.find_fuzzy("device is already in use by", "label")
alert.find_pattern("Yes", "push button").click()
uiutils.check_in_loop(lambda: details.active)
# Add another USB device
self._open_addhw_window(details)
tab = self._select_hw(addhw, "USB Host Device", "host-tab")
tab.find_fuzzy("Cruzer Micro 256", "table cell").click()
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add PCI device
self._open_addhw_window(details)
tab = self._select_hw(addhw, "PCI Host Device", "host-tab")
tab.find_fuzzy("(Interface eth0)", "table cell").click()
finish.click()
alert = self.app.root.find_pattern("vmm dialog", "alert")
alert.find_fuzzy("device is already in use by", "label")
alert.find_pattern("Yes", "push button").click()
uiutils.check_in_loop(lambda: details.active)
def testAddChars(self):
"""
Add a bunch of char devices
"""
details = self._open_details_window()
addhw = self._open_addhw_window(details)
finish = addhw.find_pattern("Finish", "push button")
# Add console device
tab = self._select_hw(addhw, "Console", "char-tab")
tab.find(None, "combo box", "Device Type:").click()
tab.find_fuzzy("Pseudo TTY", "menu item").click()
tab.find(None, "combo box", "Type:").click()
tab.find_fuzzy("Hypervisor default", "menu item").click()
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add serial+file
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Serial", "char-tab")
tab.find_pattern(None, "combo box", "Device Type:").click()
tab.find_fuzzy("Output to a file", "menu item").click()
tab.find_pattern(None, "text", "Path:").text = "/tmp/foo.log"
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add udp serial
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Serial", "char-tab")
tab.find_pattern(None, "combo box", "Device Type:").click()
tab.find_fuzzy("UDP", "menu item").click()
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add parallel+device
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Parallel", "char-tab")
tab.find_pattern(None, "combo box", "Device Type:").click()
tab.find_fuzzy("Physical host character", "menu item").click()
tab.find_pattern(None, "text", "Path:").text = "/dev/parallel0"
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add spicevmc channel
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Channel", "char-tab")
# Ensures that this is selected by default
tab.find_pattern("com.redhat.spice.0", "combo box")
finish.click()
uiutils.check_in_loop(lambda: details.active)
def testAddLXCFilesystem(self):
"""
Adding LXC specific filesystems
"""
self.app.uri = tests.utils.uri_lxc
details = self._open_details_window()
addhw = self._open_addhw_window(details)
finish = addhw.find_pattern("Finish", "push button")
# Add File+nbd share
tab = self._select_hw(addhw, "Filesystem", "filesystem-tab")
tab.find_pattern(None, "combo box", "Type:").click()
tab.find_pattern("File", "menu item").click()
tab.find_pattern(None, "combo box", "Driver:").click()
tab.find_pattern("Nbd", "menu item").click()
tab.find_pattern(None, "combo box", "Format:").click()
tab.find_pattern("qcow2", "menu item").click()
tab.find_pattern("Browse...", "push button").click()
browsewin = self.app.root.find_pattern(
"Choose Storage Volume", "frame")
browsewin.find_pattern("Cancel", "push button").click()
uiutils.check_in_loop(lambda: addhw.active)
tab.find_fuzzy(None, "text", "Source path:").text = "/foo/source"
tab.find_fuzzy(None, "text", "Target path:").text = "/foo/target"
tab.find_fuzzy("Export filesystem", "check").click()
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add RAM type
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Filesystem", "filesystem-tab")
tab.find_pattern(None, "combo box", "Type:").click()
tab.find_pattern("Ram", "menu item").click()
tab.find_pattern(None, "spin button", "Usage:").text = "12345"
tab.find_fuzzy(None, "text", "Target path:").text = "/mem"
finish.click()
uiutils.check_in_loop(lambda: details.active)
def testAddHWMisc(self):
"""
Add one each of simple devices
"""
details = self._open_details_window()
addhw = self._open_addhw_window(details)
finish = addhw.find_pattern("Finish", "push button")
# Add input
tab = self._select_hw(addhw, "Input", "input-tab")
tab.find_pattern(None, "combo box", "Type:").click()
tab.find_pattern("EvTouch", "menu item").click()
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add sound
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Sound", "sound-tab")
tab.find_pattern(None, "combo box", "Model:").click()
tab.find_pattern("ich6", "menu item").click()
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add video
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Video", "video-tab")
tab.find_pattern(None, "combo box", "Model:").click()
tab.find_pattern("QXL", "menu item").click()
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add watchdog
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Watchdog", "watchdog-tab")
tab.find_pattern(None, "combo box", "Model:").click()
tab.find_pattern("i6300esb", "menu item").click()
tab.find_pattern(None, "combo box", "Action:").click()
tab.find_pattern("Pause the guest", "menu item").click()
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add smartcard
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Smartcard", "smartcard-tab")
tab.find_pattern(None, "combo box", "Mode:").click()
tab.find_pattern("Passthrough", "menu item").click()
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add basic filesystem
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Filesystem", "filesystem-tab")
tab.find_fuzzy(None, "text", "Source path:").text = "/foo/source"
tab.find_fuzzy(None, "text", "Target path:").text = "/foo/target"
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add TPM
self._open_addhw_window(details)
tab = self._select_hw(addhw, "TPM", "tpm-tab")
tab.find_pattern(None, "text", "Device Path:").text = "/tmp/foo"
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add RNG
self._open_addhw_window(details)
tab = self._select_hw(addhw, "RNG", "rng-tab")
tab.find_pattern(None, "text", "Device:").text = "/dev/random"
finish.click()
uiutils.check_in_loop(lambda: details.active)
# Add Panic
self._open_addhw_window(details)
tab = self._select_hw(addhw, "Panic", "panic-tab")
tab.find_pattern(None, "combo box", "Model:").click()
tab.find_pattern("Hyper-V", "menu item").click()
finish.click()
uiutils.check_in_loop(lambda: details.active)

View File

@ -24,8 +24,13 @@ class UITestCase(unittest.TestCase):
def tearDown(self):
self.app.stop()
# A little helper to save test files from having to import time
sleep = time.sleep
# Helpers to save testfile imports
@staticmethod
def sleep(*args, **kwargs):
return time.sleep(*args, **kwargs)
@staticmethod
def pressKey(*args, **kwargs):
return dogtail.rawinput.pressKey(*args, **kwargs)
def _open_host_window(self, tab, conn_label="test testdriver.xml"):
"""
@ -150,6 +155,16 @@ class VMMDogtailNode(dogtail.tree.Node):
def state_selected(self):
return self.getState().contains(pyatspi.STATE_SELECTED)
def click_combo_entry(self):
"""
Helper for clicking the arrow of a combo entry, to expose the menu.
Clicks middle of Y axis, but 1 pixel in from the right side
"""
button = 1
clickX = self.position[0] + self.size[0] - 1
clickY = self.position[1] + self.size[1] / 2
dogtail.rawinput.click(clickX, clickY, button)
#########################
# Widget search helpers #
@ -203,7 +218,6 @@ class VMMDogtailNode(dogtail.tree.Node):
msg += " labeller.text='%s'" % self.labeller.text
return msg
def print_nodes(self):
"""
Helper to print the entire node tree for the passed root. Useful

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.2 -->
<interface>
<requires lib="gtk+" version="3.14"/>
<object class="GtkAdjustment" id="adjustment1">
@ -270,6 +270,11 @@
<property name="position">2</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="vbox10-atkobject">
<property name="AtkObject::accessible-name">storage-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
@ -364,6 +369,11 @@
<child>
<placeholder/>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="grid5-atkobject">
<property name="AtkObject::accessible-name">controller-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">2</property>
@ -537,6 +547,11 @@
<property name="position">1</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="box2-atkobject">
<property name="AtkObject::accessible-name">network-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">3</property>
@ -583,6 +598,11 @@
<property name="top_attach">0</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="table33-atkobject">
<property name="AtkObject::accessible-name">input-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">4</property>
@ -606,6 +626,11 @@
<child>
<placeholder/>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="graphics-align-atkobject">
<property name="AtkObject::accessible-name">graphics-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">5</property>
@ -653,6 +678,11 @@
<property name="top_attach">0</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="table2-atkobject">
<property name="AtkObject::accessible-name">sound-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">6</property>
@ -715,6 +745,11 @@
<property name="top_attach">1</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="table3-atkobject">
<property name="AtkObject::accessible-name">host-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">7</property>
@ -1073,6 +1108,11 @@
<property name="top_attach">5</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="char-table-atkobject">
<property name="AtkObject::accessible-name">char-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">8</property>
@ -1119,6 +1159,11 @@
<property name="top_attach">0</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="table5-atkobject">
<property name="AtkObject::accessible-name">video-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">9</property>
@ -1188,6 +1233,11 @@
<property name="top_attach">1</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="table6-atkobject">
<property name="AtkObject::accessible-name">watchdog-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">10</property>
@ -1212,6 +1262,11 @@
<child>
<placeholder/>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="fs-box-atkobject">
<property name="AtkObject::accessible-name">filesystem-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">11</property>
@ -1259,6 +1314,11 @@
<property name="top_attach">0</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="table10-atkobject">
<property name="AtkObject::accessible-name">smartcard-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">12</property>
@ -1372,6 +1432,11 @@
<property name="top_attach">0</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="table39-atkobject">
<property name="AtkObject::accessible-name">usbredir-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">13</property>
@ -1445,6 +1510,11 @@
<property name="top_attach">0</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="table12-atkobject">
<property name="AtkObject::accessible-name">tpm-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">14</property>
@ -1697,6 +1767,11 @@
<property name="top_attach">2</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="grid1-atkobject">
<property name="AtkObject::accessible-name">rng-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">15</property>
@ -1743,6 +1818,11 @@
<property name="top_attach">0</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="grid2-atkobject">
<property name="AtkObject::accessible-name">panic-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">16</property>
@ -1828,5 +1908,8 @@
</child>
</object>
</child>
<child type="titlebar">
<placeholder/>
</child>
</object>
</interface>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.2 -->
<interface>
<requires lib="gtk+" version="3.14"/>
<object class="GtkAdjustment" id="adjustment6">
@ -320,9 +320,9 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label">Usage:</property>
<property name="label">_Usage:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">fs-source</property>
<property name="mnemonic_widget">fs-ram-source-spin</property>
</object>
<packing>
<property name="left_attach">0</property>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.2 -->
<interface>
<requires lib="gtk+" version="3.14"/>
<object class="GtkAdjustment" id="adjustment4">
@ -56,6 +56,11 @@
<property name="visibility">False</property>
<property name="invisible_char">●</property>
<signal name="changed" handler="on_graphics_password_changed" swapped="no"/>
<child internal-child="accessible">
<object class="AtkObject" id="graphics-password-atkobject">
<property name="AtkObject::accessible-name">graphics-password</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -187,6 +192,11 @@
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_graphics_tlsport_auto_toggled" swapped="no"/>
<child internal-child="accessible">
<object class="AtkObject" id="graphics-tlsport-auto-atkobject">
<property name="AtkObject::accessible-name">graphics-tlsport-auto</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
@ -207,6 +217,11 @@
<property name="update_policy">if-valid</property>
<property name="value">5901</property>
<signal name="changed" handler="on_graphics_tlsport_changed" swapped="no"/>
<child internal-child="accessible">
<object class="AtkObject" id="graphics-tlsport-atkobject">
<property name="AtkObject::accessible-name">graphics-tlsport</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -270,6 +285,11 @@
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_graphics_port_auto_toggled" swapped="no"/>
<child internal-child="accessible">
<object class="AtkObject" id="graphics-port-auto-atkobject">
<property name="AtkObject::accessible-name">graphics-port-auto</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
@ -290,6 +310,11 @@
<property name="update_policy">if-valid</property>
<property name="value">5900</property>
<signal name="changed" handler="on_graphics_port_changed" swapped="no"/>
<child internal-child="accessible">
<object class="AtkObject" id="graphics-port-atkobject">
<property name="AtkObject::accessible-name">graphics-port</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -395,6 +420,7 @@
<property name="valign">start</property>
<property name="label" translatable="yes">Open_GL:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">graphics-opengl</property>
</object>
<packing>
<property name="left_attach">0</property>
@ -460,7 +486,6 @@
</child>
<child>
<object class="GtkImage" id="graphics-opengl-warn">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-dialog-warning</property>
</object>
@ -494,6 +519,11 @@
<property name="halign">start</property>
</object>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="graphics-rendernode-atkobject">
<property name="AtkObject::accessible-name">graphics-rendernode</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -503,7 +533,6 @@
</child>
<child>
<object class="GtkImage" id="graphics-rendernode-warn">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-dialog-warning</property>
</object>