diff options
author | Cole Robinson <crobinso@redhat.com> | 2018-01-18 18:18:24 -0500 |
---|---|---|
committer | Cole Robinson <crobinso@redhat.com> | 2018-01-19 11:04:44 -0500 |
commit | 9232a51d556be1d14016be1732e0fe0e2f7fd088 (patch) | |
tree | 51310c7b1d4d8e254149e46057404727c4fa0bc9 | |
parent | 402b42b14a43ed7ac878904ec209e4c7e2c2c8d3 (diff) | |
download | virt-manager-9232a51d556be1d14016be1732e0fe0e2f7fd088.tar.gz |
uitests: Add a bunch of addhardware testing
-rw-r--r-- | tests/uitests/addhardware.py | 317 | ||||
-rw-r--r-- | tests/uitests/utils.py | 20 | ||||
-rw-r--r-- | ui/addhardware.ui | 85 | ||||
-rw-r--r-- | ui/fsdetails.ui | 6 | ||||
-rw-r--r-- | ui/gfxdetails.ui | 35 |
5 files changed, 453 insertions, 10 deletions
diff --git a/tests/uitests/addhardware.py b/tests/uitests/addhardware.py new file mode 100644 index 00000000..ae82c5fd --- /dev/null +++ b/tests/uitests/addhardware.py @@ -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) diff --git a/tests/uitests/utils.py b/tests/uitests/utils.py index 69123237..4a3216af 100644 --- a/tests/uitests/utils.py +++ b/tests/uitests/utils.py @@ -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 diff --git a/ui/addhardware.ui b/ui/addhardware.ui index 44b23068..a44cb1f3 100644 --- a/ui/addhardware.ui +++ b/ui/addhardware.ui @@ -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> diff --git a/ui/fsdetails.ui b/ui/fsdetails.ui index 17315cb4..86df76be 100644 --- a/ui/fsdetails.ui +++ b/ui/fsdetails.ui @@ -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> diff --git a/ui/gfxdetails.ui b/ui/gfxdetails.ui index 2f44ec92..e4b38cf0 100644 --- a/ui/gfxdetails.ui +++ b/ui/gfxdetails.ui @@ -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> |