uitests: big mess of work
* Convert to pytest style functions * Move lots of shared code to our App class * Reduce dogtail sleep amounts to speed up the whole testsuite * Improve robustness in a lot of areas Signed-off-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
parent
799c82584c
commit
8ce83dbc53
|
@ -5,4 +5,3 @@ from . import _dogtailinit
|
|||
from . import _node
|
||||
from . import app
|
||||
from . import utils
|
||||
from . import testcase
|
||||
|
|
|
@ -16,11 +16,13 @@ gi.require_version('Atspi', '2.0')
|
|||
import dogtail.config
|
||||
import dogtail.utils
|
||||
|
||||
# Perform 5 search attempts if a widget lookup fails (default 20)
|
||||
dogtail.config.config.searchCutoffCount = 5
|
||||
# find() backoff handling
|
||||
dogtail.config.config.searchBackoffDuration = .1
|
||||
dogtail.config.config.searchCutoffCount = 20
|
||||
|
||||
# Use .1 second delay between each action (default 1)
|
||||
dogtail.config.config.actionDelay = .1
|
||||
dogtail.config.config.defaultDelay = .1
|
||||
|
||||
# Turn off needlessly noisy debugging
|
||||
DOGTAIL_DEBUG = False
|
||||
|
|
|
@ -210,7 +210,17 @@ class _VMMDogtailNode(dogtail.tree.Node):
|
|||
# pylint: disable=arguments-differ,signature-differs
|
||||
self.check_onscreen()
|
||||
self.check_sensitive()
|
||||
dogtail.tree.Node.click(self, *args, **kwargs)
|
||||
super().click(*args, **kwargs)
|
||||
|
||||
def point(self, *args, **kwargs):
|
||||
# pylint: disable=signature-differs
|
||||
super().point(*args, **kwargs)
|
||||
|
||||
if (self.roleName == "menu" and
|
||||
self.accessible_parent.roleName == "menu"):
|
||||
# Widget is a submenu, make sure the item is in selected
|
||||
# state before we return
|
||||
utils.check(lambda: self.state_selected)
|
||||
|
||||
def set_text(self, text):
|
||||
self.check_onscreen()
|
||||
|
@ -231,12 +241,29 @@ class _VMMDogtailNode(dogtail.tree.Node):
|
|||
raise RuntimeError("Could not bring widget on screen")
|
||||
return self
|
||||
|
||||
def window_maximize(self):
|
||||
assert self.roleName in ["frame", "dialog"]
|
||||
utils.check(lambda: self.active)
|
||||
self.click_title()
|
||||
s1 = self.size
|
||||
self.keyCombo("<alt>F10")
|
||||
utils.check(lambda: self.size != s1)
|
||||
self.grabFocus()
|
||||
|
||||
def window_close(self):
|
||||
assert self.roleName in ["frame", "alert", "dialog"]
|
||||
self.click_title()
|
||||
utils.check(lambda: self.active)
|
||||
self.keyCombo("<alt>F4")
|
||||
utils.check(lambda: not self.showing)
|
||||
|
||||
|
||||
#########################
|
||||
# Widget search helpers #
|
||||
#########################
|
||||
|
||||
def find(self, name, roleName=None, labeller_text=None, check_active=True):
|
||||
def find(self, name, roleName=None, labeller_text=None,
|
||||
check_active=True, recursive=True):
|
||||
"""
|
||||
Search root for any widget that contains the passed name/role regex
|
||||
strings.
|
||||
|
@ -244,7 +271,7 @@ class _VMMDogtailNode(dogtail.tree.Node):
|
|||
pred = _FuzzyPredicate(name, roleName, labeller_text)
|
||||
|
||||
try:
|
||||
ret = self.findChild(pred)
|
||||
ret = self.findChild(pred, recursive=recursive)
|
||||
except dogtail.tree.SearchError:
|
||||
raise dogtail.tree.SearchError("Didn't find widget with name='%s' "
|
||||
"roleName='%s' labeller_text='%s'" %
|
||||
|
@ -325,6 +352,9 @@ class _VMMDogtailNode(dogtail.tree.Node):
|
|||
"""
|
||||
print(self.fmt_nodes())
|
||||
|
||||
def print_states(self):
|
||||
print([s.value_nick for s in self.getState().get_states()])
|
||||
|
||||
|
||||
# This is the same hack dogtail uses to extend the Accessible class.
|
||||
_bases = list(pyatspi.Accessibility.Accessible.__bases__)
|
||||
|
|
|
@ -24,6 +24,7 @@ class VMMDogtailApp(object):
|
|||
self._proc = None
|
||||
self._root = None
|
||||
self._topwin = None
|
||||
self._manager = None
|
||||
self.uri = uri
|
||||
|
||||
|
||||
|
@ -37,6 +38,11 @@ class VMMDogtailApp(object):
|
|||
def sleep(self, *args, **kwargs):
|
||||
return time.sleep(*args, **kwargs)
|
||||
|
||||
def find_window(self, name, roleName=None):
|
||||
if roleName is None:
|
||||
roleName = "(frame|dialog|alert|window)"
|
||||
return self.root.find(name=name, roleName=roleName, recursive=False)
|
||||
|
||||
rawinput = dogtail.rawinput
|
||||
tree = dogtail.tree
|
||||
|
||||
|
@ -45,27 +51,16 @@ class VMMDogtailApp(object):
|
|||
# virt-manager specific helpers #
|
||||
#################################
|
||||
|
||||
def open_host_window(self, tab, conn_label="test testdriver.xml"):
|
||||
"""
|
||||
Helper to open host connection window and switch to a tab
|
||||
"""
|
||||
self.root.find_fuzzy(conn_label, "table cell").click()
|
||||
self.root.find_fuzzy("Edit", "menu").click()
|
||||
self.root.find_fuzzy("Connection Details", "menu item").click()
|
||||
win = self.root.find_fuzzy(
|
||||
"%s - Connection Details" % conn_label, "frame")
|
||||
win.find_fuzzy(tab, "page tab").click()
|
||||
return win
|
||||
def get_manager(self):
|
||||
if not self._manager:
|
||||
self._manager = self.find_window("Virtual Machine Manager")
|
||||
return self._manager
|
||||
|
||||
def open_details_window(self, vmname, shutdown=False, double=False):
|
||||
if double:
|
||||
self.root.find_fuzzy(vmname, "table cell").doubleClick()
|
||||
else:
|
||||
self.root.find_fuzzy(vmname, "table cell").click(button=3)
|
||||
self.root.find("Open", "menu item").click()
|
||||
|
||||
win = self.root.find("%s on" % vmname, "frame")
|
||||
win.find("Details", "radio button").click()
|
||||
def find_details_window(self, vmname,
|
||||
click_details=False, shutdown=False):
|
||||
win = self.find_window("%s on" % vmname, "frame")
|
||||
if click_details:
|
||||
win.find("Details", "radio button").click()
|
||||
if shutdown:
|
||||
win.find("Shut Down", "push button").click()
|
||||
run = win.find("Run", "push button")
|
||||
|
@ -73,13 +68,13 @@ class VMMDogtailApp(object):
|
|||
return win
|
||||
|
||||
def click_alert_button(self, label_text, button_text):
|
||||
alert = self.root.find("vmm dialog", "alert")
|
||||
alert = self.find_window("vmm dialog", "alert")
|
||||
alert.find_fuzzy(label_text, "label")
|
||||
alert.find(button_text, "push button").click()
|
||||
utils.check(lambda: not alert.active)
|
||||
|
||||
def select_storagebrowser_volume(self, pool, vol, doubleclick=False):
|
||||
browsewin = self.root.find("vmm-storage-browser")
|
||||
browsewin = self.find_window("vmm-storage-browser")
|
||||
browsewin.find_fuzzy(pool, "table cell").click()
|
||||
volcell = browsewin.find_fuzzy(vol, "table cell")
|
||||
if doubleclick:
|
||||
|
@ -90,6 +85,134 @@ class VMMDogtailApp(object):
|
|||
utils.check(lambda: not browsewin.active)
|
||||
|
||||
|
||||
##########################
|
||||
# manager window helpers #
|
||||
##########################
|
||||
|
||||
def manager_open_createconn(self):
|
||||
manager = self.get_manager()
|
||||
manager.find("File", "menu").click()
|
||||
manager.find("Add Connection...", "menu item").click()
|
||||
win = self.root.find("Add Connection", "dialog")
|
||||
return win
|
||||
|
||||
def manager_createconn(self, uri):
|
||||
win = self.manager_open_createconn()
|
||||
win.combo_select("Hypervisor", "Custom URI")
|
||||
win.find("uri-entry", "text").set_text(uri)
|
||||
win.find("Connect", "push button").click()
|
||||
utils.check(lambda: win.showing is False)
|
||||
|
||||
def manager_get_conn_cell(self, conn_label):
|
||||
return self.get_manager().find(conn_label, "table cell")
|
||||
|
||||
def manager_conn_connect(self, conn_label):
|
||||
c = self.manager_get_conn_cell(conn_label)
|
||||
c.click(button=3)
|
||||
self.root.find("conn-connect", "menu item").click()
|
||||
utils.check(lambda: "Not Connected" not in c.text)
|
||||
return c
|
||||
|
||||
def manager_conn_disconnect(self, conn_label):
|
||||
c = self.manager_get_conn_cell(conn_label)
|
||||
c.click(button=3)
|
||||
self.root.find("conn-disconnect", "menu item").click()
|
||||
utils.check(lambda: "Not Connected" in c.text)
|
||||
return c
|
||||
|
||||
def manager_conn_delete(self, conn_label):
|
||||
c = self.manager_get_conn_cell(conn_label)
|
||||
c.click(button=3)
|
||||
self.root.find("conn-delete", "menu item").click()
|
||||
self.click_alert_button("will remove the connection", "Yes")
|
||||
utils.check(lambda: c.dead)
|
||||
|
||||
def manager_vm_action(self, vmname, confirm_click_no=False,
|
||||
run=False, shutdown=False, destroy=False, reset=False,
|
||||
reboot=False, pause=False, resume=False, save=False,
|
||||
restore=False, clone=False, migrate=False, delete=False,
|
||||
details=False):
|
||||
manager = self.get_manager()
|
||||
vmcell = manager.find(vmname + "\n", "table cell")
|
||||
|
||||
if run:
|
||||
action = "Run"
|
||||
if shutdown:
|
||||
action = "Shut Down"
|
||||
if reboot:
|
||||
action = "Reboot"
|
||||
if reset:
|
||||
action = "Force Reset"
|
||||
if destroy:
|
||||
action = "Force Off"
|
||||
if pause:
|
||||
action = "Pause"
|
||||
if resume:
|
||||
action = "Resume"
|
||||
if save:
|
||||
action = "Save"
|
||||
if restore:
|
||||
action = "Restore"
|
||||
if clone:
|
||||
action = "Clone"
|
||||
if migrate:
|
||||
action = "Migrate"
|
||||
if delete:
|
||||
action = "Delete"
|
||||
if details:
|
||||
action = "Open"
|
||||
|
||||
needs_shutdown = shutdown or destroy or reset or reboot or save
|
||||
needs_confirm = needs_shutdown or pause
|
||||
|
||||
def _do_click():
|
||||
vmcell.click()
|
||||
vmcell.click(button=3)
|
||||
menu = self.root.find("vm-action-menu")
|
||||
utils.check(lambda: menu.onscreen)
|
||||
if needs_shutdown:
|
||||
smenu = menu.find("Shut Down", "menu")
|
||||
smenu.point()
|
||||
utils.check(lambda: smenu.onscreen)
|
||||
item = smenu.find(action, "menu item")
|
||||
else:
|
||||
item = menu.find(action, "menu item")
|
||||
utils.check(lambda: item.onscreen)
|
||||
item.point()
|
||||
utils.check(lambda: item.state_selected)
|
||||
item.click()
|
||||
return menu
|
||||
|
||||
m = _do_click()
|
||||
if needs_confirm:
|
||||
if confirm_click_no:
|
||||
self.click_alert_button("Are you sure", "No")
|
||||
m = _do_click()
|
||||
self.click_alert_button("Are you sure", "Yes")
|
||||
utils.check(lambda: not m.onscreen)
|
||||
|
||||
def manager_open_clone(self, vmname):
|
||||
self.manager_vm_action(vmname, clone=True)
|
||||
return self.find_window("Clone Virtual Machine")
|
||||
|
||||
def manager_open_details(self, vmname, shutdown=False):
|
||||
self.manager_vm_action(vmname, details=True)
|
||||
win = self.find_details_window(vmname,
|
||||
shutdown=shutdown, click_details=True)
|
||||
return win
|
||||
|
||||
def manager_open_host(self, tab, conn_label="test testdriver.xml"):
|
||||
"""
|
||||
Helper to open host connection window and switch to a tab
|
||||
"""
|
||||
self.root.find_fuzzy(conn_label, "table cell").click()
|
||||
self.root.find_fuzzy("Edit", "menu").click()
|
||||
self.root.find_fuzzy("Connection Details", "menu item").click()
|
||||
win = self.find_window("%s - Connection Details" % conn_label)
|
||||
win.find_fuzzy(tab, "page tab").click()
|
||||
return win
|
||||
|
||||
|
||||
###########################
|
||||
# Process management APIs #
|
||||
###########################
|
||||
|
@ -156,7 +279,7 @@ class VMMDogtailApp(object):
|
|||
window_name=None, xmleditor_enabled=False, keyfile=None,
|
||||
break_setfacl=False, first_run=True, no_fork=True,
|
||||
will_fail=False, enable_libguestfs=False,
|
||||
firstrun_uri=None):
|
||||
firstrun_uri=None, show_console=None):
|
||||
extra_opts = extra_opts or []
|
||||
uri = uri or self.uri
|
||||
|
||||
|
@ -174,6 +297,8 @@ class VMMDogtailApp(object):
|
|||
cmd += ["--no-fork"]
|
||||
if use_uri:
|
||||
cmd += ["--connect", uri]
|
||||
if show_console:
|
||||
cmd += ["--show-domain-console=%s" % show_console]
|
||||
|
||||
if first_run:
|
||||
cmd.append("--test-options=first-run")
|
||||
|
@ -205,4 +330,4 @@ class VMMDogtailApp(object):
|
|||
self._proc = subprocess.Popen(cmd, stdout=stdout, stderr=stderr)
|
||||
if not will_fail:
|
||||
self._root = dogtail.tree.root.application("virt-manager")
|
||||
self._topwin = self._root.find(window_name, "(frame|dialog|alert)")
|
||||
self._topwin = self.find_window(window_name)
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
# This work is licensed under the GNU GPLv2 or later.
|
||||
# See the COPYING file in the top-level directory.
|
||||
|
||||
import unittest
|
||||
|
||||
from .app import VMMDogtailApp
|
||||
|
||||
|
||||
class UITestCase(unittest.TestCase):
|
||||
"""
|
||||
Common testcase bits shared for ui tests
|
||||
"""
|
||||
def setUp(self):
|
||||
self.app = VMMDogtailApp()
|
||||
def tearDown(self):
|
||||
self.app.stop()
|
File diff suppressed because it is too large
Load Diff
|
@ -6,192 +6,201 @@ import unittest.mock
|
|||
from . import lib
|
||||
|
||||
|
||||
class VMMCLI(lib.testcase.UITestCase):
|
||||
# UI tests for virt-manager's command line --show options
|
||||
|
||||
|
||||
def testShowNewVM(app):
|
||||
app.open(
|
||||
uri="test:///default",
|
||||
extra_opts=["--show-domain-creator"])
|
||||
lib.utils.check(lambda: app.topwin.name == "New VM")
|
||||
app.topwin.keyCombo("<alt>F4")
|
||||
app.wait_for_exit()
|
||||
|
||||
|
||||
def testShowHost(app):
|
||||
app.open(
|
||||
uri="test:///default",
|
||||
extra_opts=["--show-host-summary"])
|
||||
|
||||
lib.utils.check(lambda: app.topwin.name == "test default - Connection Details")
|
||||
nametext = app.topwin.find_fuzzy("Name:", "text")
|
||||
lib.utils.check(lambda: nametext.text == "test default")
|
||||
app.topwin.keyCombo("<alt>F4")
|
||||
app.wait_for_exit()
|
||||
|
||||
|
||||
def testShowDetails(app):
|
||||
app.open(
|
||||
extra_opts=["--show-domain-editor", "test-clone-simple"])
|
||||
|
||||
lib.utils.check(lambda: "test-clone-simple on" in app.topwin.name)
|
||||
rlabel = app.topwin.find_fuzzy("Guest is not running", "label")
|
||||
lib.utils.check(lambda: not rlabel.showing)
|
||||
addhw = app.topwin.find_fuzzy("add-hardware", "button")
|
||||
lib.utils.check(lambda: addhw.showing)
|
||||
app.topwin.keyCombo("<alt>F4")
|
||||
app.wait_for_exit()
|
||||
|
||||
|
||||
def testShowPerformance(app):
|
||||
domid = "1"
|
||||
app.open(
|
||||
uri="test:///default",
|
||||
extra_opts=["--show-domain-performance", domid])
|
||||
|
||||
lib.utils.check(lambda: "test on" in app.topwin.name)
|
||||
cpulabel = app.topwin.find_fuzzy("CPU usage", "label")
|
||||
lib.utils.check(lambda: cpulabel.showing)
|
||||
|
||||
|
||||
def testShowConsole(app):
|
||||
# UUID of test-clone-simple
|
||||
uuid = "12345678-1234-ffff-1234-12345678ffff"
|
||||
app.open(
|
||||
extra_opts=["--show-domain-console", uuid])
|
||||
|
||||
lib.utils.check(lambda: "test-clone-simple on" in app.topwin.name)
|
||||
rlabel = app.topwin.find_fuzzy("Guest is not running", "label")
|
||||
lib.utils.check(lambda: rlabel.showing)
|
||||
addhw = app.topwin.find_fuzzy("add-hardware", "button")
|
||||
lib.utils.check(lambda: not addhw.showing)
|
||||
|
||||
|
||||
def testShowDelete(app):
|
||||
app.open(
|
||||
uri="test:///default",
|
||||
extra_opts=["--show-domain-delete", "test"],
|
||||
window_name="Delete")
|
||||
# Ensure details opened too
|
||||
app.root.find("test on", "frame", check_active=False)
|
||||
|
||||
delete = app.topwin
|
||||
delete.find_fuzzy("Delete", "button").click()
|
||||
app.wait_for_exit()
|
||||
|
||||
|
||||
|
||||
def testShowRemoteDBusConnect(app):
|
||||
"""
|
||||
UI tests for virt-manager's command line --show options
|
||||
Test the remote app dbus connection
|
||||
"""
|
||||
app.open()
|
||||
lib.utils.check(lambda: "testdriver" in app.topwin.fmt_nodes())
|
||||
lib.utils.check(lambda: "test default" not in app.topwin.fmt_nodes())
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
def _run_remote(opts):
|
||||
newapp = lib.app.VMMDogtailApp("test:///default")
|
||||
newapp.open(check_already_running=False,
|
||||
extra_opts=opts)
|
||||
lib.utils.check(lambda: not newapp.is_running())
|
||||
vapps = [a for a in newapp.tree.root.applications() if
|
||||
a.name == "virt-manager"]
|
||||
lib.utils.check(lambda: len(vapps) == 1)
|
||||
# Ensure connection showed up
|
||||
app.topwin.find("test default", "table cell")
|
||||
|
||||
def testShowNewVM(self):
|
||||
self.app.open(
|
||||
uri="test:///default",
|
||||
extra_opts=["--show-domain-creator"])
|
||||
lib.utils.check(lambda: self.app.topwin.name == "New VM")
|
||||
self.app.topwin.keyCombo("<alt>F4")
|
||||
self.app.wait_for_exit()
|
||||
|
||||
def testShowHost(self):
|
||||
self.app.open(
|
||||
uri="test:///default",
|
||||
extra_opts=["--show-host-summary"])
|
||||
|
||||
lib.utils.check(lambda: self.app.topwin.name == "test default - Connection Details")
|
||||
nametext = self.app.topwin.find_fuzzy("Name:", "text")
|
||||
lib.utils.check(lambda: nametext.text == "test default")
|
||||
self.app.topwin.keyCombo("<alt>F4")
|
||||
self.app.wait_for_exit()
|
||||
|
||||
def testShowDetails(self):
|
||||
self.app.open(
|
||||
extra_opts=["--show-domain-editor", "test-clone-simple"])
|
||||
|
||||
lib.utils.check(lambda: "test-clone-simple on" in self.app.topwin.name)
|
||||
rlabel = self.app.topwin.find_fuzzy("Guest is not running", "label")
|
||||
lib.utils.check(lambda: not rlabel.showing)
|
||||
addhw = self.app.topwin.find_fuzzy("add-hardware", "button")
|
||||
lib.utils.check(lambda: addhw.showing)
|
||||
self.app.topwin.keyCombo("<alt>F4")
|
||||
self.app.wait_for_exit()
|
||||
|
||||
def testShowPerformance(self):
|
||||
domid = "1"
|
||||
self.app.open(
|
||||
uri="test:///default",
|
||||
extra_opts=["--show-domain-performance", domid])
|
||||
|
||||
lib.utils.check(lambda: "test on" in self.app.topwin.name)
|
||||
cpulabel = self.app.topwin.find_fuzzy("CPU usage", "label")
|
||||
lib.utils.check(lambda: cpulabel.showing)
|
||||
|
||||
def testShowConsole(self):
|
||||
# UUID of test-clone-simple
|
||||
uuid = "12345678-1234-ffff-1234-12345678ffff"
|
||||
self.app.open(
|
||||
extra_opts=["--show-domain-console", uuid])
|
||||
|
||||
lib.utils.check(lambda: "test-clone-simple on" in self.app.topwin.name)
|
||||
rlabel = self.app.topwin.find_fuzzy("Guest is not running", "label")
|
||||
lib.utils.check(lambda: rlabel.showing)
|
||||
addhw = self.app.topwin.find_fuzzy("add-hardware", "button")
|
||||
lib.utils.check(lambda: not addhw.showing)
|
||||
|
||||
def testShowDelete(self):
|
||||
self.app.open(
|
||||
uri="test:///default",
|
||||
extra_opts=["--show-domain-delete", "test"],
|
||||
window_name="Delete")
|
||||
# Ensure details opened too
|
||||
self.app.root.find("test on", "frame",
|
||||
check_active=False)
|
||||
|
||||
delete = self.app.topwin
|
||||
delete.find_fuzzy("Delete", "button").click()
|
||||
self.app.wait_for_exit()
|
||||
_run_remote([])
|
||||
# Run remote again to trigger engine.py code when a connection
|
||||
# is already there and connected
|
||||
_run_remote(["--show-domain-console=test"])
|
||||
|
||||
|
||||
def testShowRemoteDBusConnect(self):
|
||||
"""
|
||||
Test the remote app dbus connection
|
||||
"""
|
||||
self.app.open()
|
||||
lib.utils.check(lambda: "testdriver" in self.app.topwin.fmt_nodes())
|
||||
lib.utils.check(lambda: "test default" not in self.app.topwin.fmt_nodes())
|
||||
def testShowCLIError(app):
|
||||
# Unknown option
|
||||
app.open(
|
||||
extra_opts=["--idontexist"])
|
||||
app.click_alert_button("Unhandled command line", "Close")
|
||||
lib.utils.check(lambda: not app.is_running())
|
||||
|
||||
def _run_remote(opts):
|
||||
newapp = lib.app.VMMDogtailApp("test:///default")
|
||||
newapp.open(check_already_running=False,
|
||||
extra_opts=opts)
|
||||
lib.utils.check(lambda: not newapp.is_running())
|
||||
vapps = [a for a in newapp.tree.root.applications() if
|
||||
a.name == "virt-manager"]
|
||||
lib.utils.check(lambda: len(vapps) == 1)
|
||||
# Ensure connection showed up
|
||||
self.app.topwin.find("test default", "table cell")
|
||||
# Missing VM
|
||||
app.open(
|
||||
uri="test:///default",
|
||||
extra_opts=["--show-domain-delete", "IDONTEXIST"])
|
||||
app.click_alert_button("does not have VM", "Close")
|
||||
lib.utils.check(lambda: not app.is_running())
|
||||
|
||||
_run_remote([])
|
||||
# Run remote again to trigger engine.py code when a connection
|
||||
# is already there and connected
|
||||
_run_remote(["--show-domain-console=test"])
|
||||
# Bad URI
|
||||
baduri = "fribfrobfroo"
|
||||
app = lib.app.VMMDogtailApp(baduri)
|
||||
app.click_alert_button(baduri, "Close")
|
||||
lib.utils.check(lambda: not app.is_running())
|
||||
|
||||
def testShowCLIError(self):
|
||||
# Unknown option
|
||||
self.app.open(
|
||||
extra_opts=["--idontexist"])
|
||||
self.app.click_alert_button("Unhandled command line", "Close")
|
||||
lib.utils.check(lambda: not self.app.is_running())
|
||||
|
||||
# Missing VM
|
||||
self.app.open(
|
||||
uri="test:///default",
|
||||
extra_opts=["--show-domain-delete", "IDONTEXIST"])
|
||||
self.app.click_alert_button("does not have VM", "Close")
|
||||
lib.utils.check(lambda: not self.app.is_running())
|
||||
def testCLIFirstRunURIGood(app):
|
||||
# Emulate first run with a URI that will succeed
|
||||
app.open(use_uri=False, firstrun_uri="test:///default")
|
||||
app.sleep(1)
|
||||
app.root.find("test default", "table cell")
|
||||
|
||||
# Bad URI
|
||||
baduri = "fribfrobfroo"
|
||||
self.app = lib.app.VMMDogtailApp(baduri)
|
||||
self.app.click_alert_button(baduri, "Close")
|
||||
lib.utils.check(lambda: not self.app.is_running())
|
||||
|
||||
def testCLIFirstRunURIGood(self):
|
||||
# Emulate first run with a URI that will succeed
|
||||
self.app.open(use_uri=False, firstrun_uri="test:///default")
|
||||
self.app.sleep(1)
|
||||
self.app.root.find("test default", "table cell")
|
||||
def testCLIFirstRunURIBad(app):
|
||||
# Emulate first run with a URI that will not succeed
|
||||
app.open(use_uri=False, firstrun_uri="bad:///uri")
|
||||
app.sleep(1)
|
||||
app.topwin.find("bad uri", "table cell")
|
||||
app.click_alert_button("bad:///uri", "Close")
|
||||
|
||||
def testCLIFirstRunURIBad(self):
|
||||
# Emulate first run with a URI that will not succeed
|
||||
self.app.open(use_uri=False, firstrun_uri="bad:///uri")
|
||||
self.app.sleep(1)
|
||||
self.app.topwin.find("bad uri", "table cell")
|
||||
self.app.click_alert_button("bad:///uri", "Close")
|
||||
|
||||
def testCLIFirstRunNoLibvirtd(self):
|
||||
# Emulate first run with no libvirtd detected
|
||||
self.app.open(use_uri=False, firstrun_uri="bad:///uri",
|
||||
extra_opts=["--test-options=fake-no-libvirtd"])
|
||||
errlabel = self.app.topwin.find("error-label")
|
||||
lib.utils.check(
|
||||
lambda: "Checking for virtualization" in errlabel.text)
|
||||
lib.utils.check(
|
||||
lambda: "libvirtd service does not appear" in errlabel.text)
|
||||
lib.utils.check(
|
||||
lambda: "detect a default hypervisor" in errlabel.text)
|
||||
def testCLIFirstRunNoLibvirtd(app):
|
||||
# Emulate first run with no libvirtd detected
|
||||
app.open(use_uri=False, firstrun_uri="bad:///uri",
|
||||
extra_opts=["--test-options=fake-no-libvirtd"])
|
||||
errlabel = app.topwin.find("error-label")
|
||||
lib.utils.check(
|
||||
lambda: "Checking for virtualization" in errlabel.text)
|
||||
lib.utils.check(
|
||||
lambda: "libvirtd service does not appear" in errlabel.text)
|
||||
lib.utils.check(
|
||||
lambda: "detect a default hypervisor" in errlabel.text)
|
||||
|
||||
def testCLITraceLibvirt(self):
|
||||
# Just test this for code coverage
|
||||
self.app.open(keyfile="allstats.ini",
|
||||
extra_opts=["--trace-libvirt=mainloop"])
|
||||
# Give it a little time to work
|
||||
self.app.sleep(2)
|
||||
lib.utils.check(lambda: self.app.topwin.active)
|
||||
|
||||
def testCLILeakDebug(self):
|
||||
# Just test this for code coverage
|
||||
self.app.open(keyfile="allstats.ini",
|
||||
extra_opts=["--test-options=leak-debug"])
|
||||
self.app.sleep(2)
|
||||
# Give it a little time to work
|
||||
lib.utils.check(lambda: self.app.topwin.active)
|
||||
self.app.topwin.keyCombo("<alt>F4")
|
||||
self.app.wait_for_exit()
|
||||
def testCLITraceLibvirt(app):
|
||||
# Just test this for code coverage
|
||||
app.open(keyfile="allstats.ini",
|
||||
extra_opts=["--trace-libvirt=mainloop"])
|
||||
# Give it a little time to work
|
||||
app.sleep(2)
|
||||
lib.utils.check(lambda: app.topwin.active)
|
||||
|
||||
def testCLINoFirstRun(self):
|
||||
# Test a simple case of loading without any config override
|
||||
self.app.open(first_run=False, enable_libguestfs=None, use_uri=False)
|
||||
self.app.sleep(2)
|
||||
lib.utils.check(lambda: self.app.topwin.showing)
|
||||
|
||||
def testCLINoFork(self):
|
||||
# Test app without forking
|
||||
self.app.open(first_run=False, enable_libguestfs=None,
|
||||
use_uri=False, no_fork=False)
|
||||
self.app.wait_for_exit()
|
||||
lib.utils.check(lambda: self.app.topwin.showing)
|
||||
self.app.topwin.keyCombo("<alt>F4")
|
||||
# Wait for app to exit, we don't have any other way
|
||||
self.app.sleep(2)
|
||||
def testCLILeakDebug(app):
|
||||
# Just test this for code coverage
|
||||
app.open(keyfile="allstats.ini",
|
||||
extra_opts=["--test-options=leak-debug"])
|
||||
app.sleep(2)
|
||||
# Give it a little time to work
|
||||
lib.utils.check(lambda: app.topwin.active)
|
||||
app.topwin.keyCombo("<alt>F4")
|
||||
app.wait_for_exit()
|
||||
|
||||
def testCLIGTKArgs(self):
|
||||
# Ensure gtk arg passthrough works
|
||||
self.app.open(extra_opts=["--gtk-debug=misc"])
|
||||
lib.utils.check(lambda: self.app.topwin.showing)
|
||||
|
||||
@unittest.mock.patch.dict('os.environ', {"DISPLAY": ""})
|
||||
def testCLINoDisplay(self):
|
||||
# Ensure missing display exits
|
||||
self.app.open(will_fail=True)
|
||||
self.app.wait_for_exit()
|
||||
def testCLINoFirstRun(app):
|
||||
# Test a simple case of loading without any config override
|
||||
app.open(first_run=False, enable_libguestfs=None, use_uri=False)
|
||||
app.sleep(2)
|
||||
lib.utils.check(lambda: app.topwin.showing)
|
||||
|
||||
|
||||
def testCLINoFork(app):
|
||||
# Test app without forking
|
||||
app.open(first_run=False, enable_libguestfs=None,
|
||||
use_uri=False, no_fork=False)
|
||||
app.wait_for_exit()
|
||||
lib.utils.check(lambda: app.topwin.showing)
|
||||
app.topwin.keyCombo("<alt>F4")
|
||||
# Wait for app to exit, we don't have any other way
|
||||
app.sleep(2)
|
||||
|
||||
|
||||
def testCLIGTKArgs(app):
|
||||
# Ensure gtk arg passthrough works
|
||||
app.open(extra_opts=["--gtk-debug=misc"])
|
||||
lib.utils.check(lambda: app.topwin.showing)
|
||||
|
||||
|
||||
@unittest.mock.patch.dict('os.environ', {"DISPLAY": ""})
|
||||
def testCLINoDisplay(app):
|
||||
# Ensure missing display exits
|
||||
app.open(will_fail=True)
|
||||
app.wait_for_exit()
|
||||
|
|
|
@ -27,240 +27,225 @@ class _CloneRow:
|
|||
self.txtcell.click()
|
||||
|
||||
|
||||
class CloneVM(lib.testcase.UITestCase):
|
||||
"""
|
||||
UI tests for virt-manager's CloneVM wizard
|
||||
"""
|
||||
def _get_all_rows(win):
|
||||
slist = win.find("storage-list")
|
||||
def pred(node):
|
||||
return node.roleName == "table cell"
|
||||
cells = slist.findChildren(pred, isLambda=True)
|
||||
|
||||
###################
|
||||
# Private helpers #
|
||||
###################
|
||||
|
||||
def _open_window(self, vmname):
|
||||
# Launch wizard via right click menu
|
||||
manager = self.app.topwin
|
||||
manager.click_title()
|
||||
lib.utils.check(lambda: manager.active)
|
||||
c = manager.find_fuzzy(vmname, "table cell")
|
||||
self.app.sleep(.3)
|
||||
c.click()
|
||||
c.click(button=3)
|
||||
item = self.app.root.find("Clone...", "menu item")
|
||||
item.point()
|
||||
self.app.sleep(.5)
|
||||
item.click()
|
||||
return self.app.root.find("Clone Virtual Machine", "frame")
|
||||
|
||||
def _get_all_rows(self, win):
|
||||
slist = win.find("storage-list")
|
||||
def pred(node):
|
||||
return node.roleName == "table cell"
|
||||
cells = slist.findChildren(pred, isLambda=True)
|
||||
|
||||
idx = 0
|
||||
rows = []
|
||||
cellcount = 6
|
||||
while idx < len(cells):
|
||||
rows.append(_CloneRow(*cells[idx:idx + cellcount]))
|
||||
idx += cellcount
|
||||
# Skip the next row which is always a separator
|
||||
idx += cellcount
|
||||
return rows
|
||||
idx = 0
|
||||
rows = []
|
||||
cellcount = 6
|
||||
while idx < len(cells):
|
||||
rows.append(_CloneRow(*cells[idx:idx + cellcount]))
|
||||
idx += cellcount
|
||||
# Skip the next row which is always a separator
|
||||
idx += cellcount
|
||||
return rows
|
||||
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
##############################################
|
||||
# UI tests for virt-manager's CloneVM wizard #
|
||||
##############################################
|
||||
|
||||
def testCloneSimple(self):
|
||||
# Disable predictable so UUID generation doesn't collide
|
||||
uri = tests.utils.URIs.test_full.replace(",predictable", "")
|
||||
self.app.uri = uri
|
||||
def testCloneSimple(app):
|
||||
# Disable predictable so UUID generation doesn't collide
|
||||
uri = tests.utils.URIs.test_full.replace(",predictable", "")
|
||||
app.uri = uri
|
||||
|
||||
# Clone 'test-clone-simple' which is the most basic case
|
||||
# Cancel, and reopen
|
||||
win = self._open_window("test-clone-simple")
|
||||
win.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
# Clone 'test-clone-simple' which is the most basic case
|
||||
# Cancel, and reopen
|
||||
win = app.manager_open_clone("test-clone-simple")
|
||||
win.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
# Do default clone
|
||||
win = self._open_window("test-clone-simple")
|
||||
rows = self._get_all_rows(win)
|
||||
assert len(rows) == 1
|
||||
assert rows[0].is_clone_requested
|
||||
rows[0].check_in_text("test-clone-simple.img")
|
||||
# Do default clone
|
||||
win = app.manager_open_clone("test-clone-simple")
|
||||
rows = _get_all_rows(win)
|
||||
assert len(rows) == 1
|
||||
assert rows[0].is_clone_requested
|
||||
rows[0].check_in_text("test-clone-simple.img")
|
||||
|
||||
win.find("Clone", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
win.find("Clone", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
# Check path was generated correctly
|
||||
win = self._open_window("test-clone-simple-clone")
|
||||
rows = self._get_all_rows(win)
|
||||
assert len(rows) == 1
|
||||
assert rows[0].is_clone_requested
|
||||
rows[0].check_in_text("test-clone-simple-clone.img")
|
||||
# Check path was generated correctly
|
||||
win = app.manager_open_clone("test-clone-simple-clone")
|
||||
rows = _get_all_rows(win)
|
||||
assert len(rows) == 1
|
||||
assert rows[0].is_clone_requested
|
||||
rows[0].check_in_text("test-clone-simple-clone.img")
|
||||
|
||||
# Share storage and deal with warnings
|
||||
rows[0].chkcell.click()
|
||||
rows[0].check_in_text("Share disk with")
|
||||
# Do 'cancel' first
|
||||
win.find("Clone", "push button").click()
|
||||
self.app.click_alert_button("cause data to be overwritten", "Cancel")
|
||||
lib.utils.check(lambda: win.active)
|
||||
win.find("Clone", "push button").click()
|
||||
self.app.click_alert_button("cause data to be overwritten", "OK")
|
||||
lib.utils.check(lambda: not win.active)
|
||||
# Share storage and deal with warnings
|
||||
rows[0].chkcell.click()
|
||||
rows[0].check_in_text("Share disk with")
|
||||
# Do 'cancel' first
|
||||
win.find("Clone", "push button").click()
|
||||
app.click_alert_button("cause data to be overwritten", "Cancel")
|
||||
lib.utils.check(lambda: win.active)
|
||||
win.find("Clone", "push button").click()
|
||||
app.click_alert_button("cause data to be overwritten", "OK")
|
||||
lib.utils.check(lambda: not win.active)
|
||||
|
||||
# Verify the new VM shared storage
|
||||
win = self._open_window("test-clone-simple-clone1")
|
||||
rows = self._get_all_rows(win)
|
||||
assert len(rows) == 1
|
||||
rows[0].check_in_text("test-clone-simple-clone.img")
|
||||
|
||||
def testCloneMulti(self):
|
||||
# Clone 'test-clone', check some results, make sure clone works
|
||||
win = self._open_window("test-clone\n")
|
||||
win.find("Clone", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
self.app.topwin.find("test-clone1", "table cell")
|
||||
|
||||
# Check test-many-devices which will not work, but confirm
|
||||
# it errors gracefully
|
||||
self.app.topwin.find("test-many-devices").click()
|
||||
sbutton = self.app.topwin.find("Shut Down", "push button")
|
||||
sbutton.click()
|
||||
lib.utils.check(lambda: not sbutton.sensitive)
|
||||
self.app.sleep(.5)
|
||||
win = self._open_window("test-many-devices")
|
||||
win.find("Clone", "push button").click()
|
||||
self.app.click_alert_button("No such file or", "Close")
|
||||
win.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
def testCloneStorageChange(self):
|
||||
# Disable predictable so UUID generation doesn't collide
|
||||
uri = tests.utils.URIs.test_full.replace(",predictable", "")
|
||||
self.app.uri = uri
|
||||
|
||||
# Trigger some error handling scenarios
|
||||
win = self._open_window("test-clone-simple")
|
||||
newname = "test-aaabbb"
|
||||
win.find("Name:", "text").set_text(newname)
|
||||
win.find("Clone", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
win = self._open_window(newname)
|
||||
row = self._get_all_rows(win)[0]
|
||||
row.check_in_text(newname)
|
||||
oldnewname = newname
|
||||
newname = "test-aaazzzzbbb"
|
||||
win.find("Name:", "text").set_text(newname)
|
||||
row.select()
|
||||
|
||||
win.find("Details", "push button").click()
|
||||
stgwin = self.app.root.find("Change storage path", "dialog")
|
||||
pathtxt = stgwin.find(None, "text", "New Path:")
|
||||
lib.utils.check(lambda: newname in pathtxt.text)
|
||||
stgwin.find("Browse", "push button").click()
|
||||
self.app.select_storagebrowser_volume("default-pool", "iso-vol")
|
||||
lib.utils.check(lambda: "iso-vol" in pathtxt.text)
|
||||
stgwin.find("OK").click()
|
||||
self.app.click_alert_button("overwrite the existing", "No")
|
||||
lib.utils.check(lambda: stgwin.showing)
|
||||
stgwin.find("OK").click()
|
||||
self.app.click_alert_button("overwrite the existing", "Yes")
|
||||
lib.utils.check(lambda: not stgwin.showing)
|
||||
# Can't clone onto existing storage volume
|
||||
win.find("Clone", "push button").click()
|
||||
self.app.click_alert_button(".*Clone onto existing.*", "Close")
|
||||
|
||||
# Reopen dialog and request to share it
|
||||
win.find("Details", "push button").click()
|
||||
stgwin = self.app.root.find("Change storage path", "dialog")
|
||||
chkbox = stgwin.find("Create a new", "check")
|
||||
lib.utils.check(lambda: chkbox.checked)
|
||||
chkbox.click()
|
||||
|
||||
# Cancel and reopen, confirm changes didn't stick
|
||||
stgwin.find("Cancel").click()
|
||||
lib.utils.check(lambda: not stgwin.showing)
|
||||
win.find("Details", "push button").click()
|
||||
stgwin = self.app.root.find("Change storage path", "dialog")
|
||||
chkbox = stgwin.find("Create a new", "check")
|
||||
lib.utils.check(lambda: chkbox.checked)
|
||||
# Requesting sharing again and exit
|
||||
chkbox.click()
|
||||
stgwin.find("OK").click()
|
||||
lib.utils.check(lambda: not stgwin.active)
|
||||
|
||||
# Finish install, verify storage was shared
|
||||
win.find("Clone", "push button").click()
|
||||
self.app.click_alert_button("cause data to be overwritten", "OK")
|
||||
lib.utils.check(lambda: not win.active)
|
||||
win = self._open_window(newname)
|
||||
row = self._get_all_rows(win)[0].check_in_text(oldnewname)
|
||||
# Verify the new VM shared storage
|
||||
win = app.manager_open_clone("test-clone-simple-clone1")
|
||||
rows = _get_all_rows(win)
|
||||
assert len(rows) == 1
|
||||
rows[0].check_in_text("test-clone-simple-clone.img")
|
||||
|
||||
|
||||
def testCloneError(self):
|
||||
# Trigger some error handling scenarios
|
||||
win = self._open_window("test-clone-full\n")
|
||||
win.find("Clone", "push button").click()
|
||||
self.app.click_alert_button("not enough free space", "Close")
|
||||
lib.utils.check(lambda: win.showing)
|
||||
win.keyCombo("<alt>F4")
|
||||
def testCloneMulti(app):
|
||||
# Clone 'test-clone', check some results, make sure clone works
|
||||
manager = app.topwin
|
||||
manager.window_maximize()
|
||||
win = app.manager_open_clone("test-clone")
|
||||
win.find("Clone", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
app.topwin.find("test-clone1", "table cell")
|
||||
|
||||
win = self._open_window("test-clone-simple")
|
||||
badname = "test/foo"
|
||||
win.find("Name:", "text").set_text(badname)
|
||||
rows = self._get_all_rows(win)
|
||||
rows[0].chkcell.click()
|
||||
rows[0].check_in_text("Share disk with")
|
||||
win.find("Clone", "push button").click()
|
||||
win.find("Clone", "push button").click()
|
||||
self.app.click_alert_button("cause data to be overwritten", "OK")
|
||||
self.app.click_alert_button(badname, "Close")
|
||||
lib.utils.check(lambda: win.active)
|
||||
# Check test-many-devices which will not work, but confirm
|
||||
# it errors gracefully
|
||||
app.topwin.find("test-many-devices").click()
|
||||
sbutton = app.topwin.find("Shut Down", "push button")
|
||||
sbutton.click()
|
||||
lib.utils.check(lambda: not sbutton.sensitive)
|
||||
app.sleep(.5)
|
||||
win = app.manager_open_clone("test-many-devices")
|
||||
win.find("Clone", "push button").click()
|
||||
app.click_alert_button("No such file or", "Close")
|
||||
|
||||
# Ensure disconnecting will close the dialog
|
||||
manager.click_title()
|
||||
app.manager_conn_disconnect("test testdriver.xml")
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
|
||||
def testCloneNonmanaged(self):
|
||||
# Verify unmanaged clone actual works
|
||||
import tempfile
|
||||
tmpsrc = tempfile.NamedTemporaryFile()
|
||||
tmpdst = tempfile.NamedTemporaryFile()
|
||||
def testCloneStorageChange(app):
|
||||
# Disable predictable so UUID generation doesn't collide
|
||||
uri = tests.utils.URIs.test_full.replace(",predictable", "")
|
||||
app.uri = uri
|
||||
|
||||
open(tmpsrc.name, "w").write(__file__)
|
||||
# Trigger some error handling scenarios
|
||||
win = app.manager_open_clone("test-clone-simple")
|
||||
newname = "test-aaabbb"
|
||||
win.find("Name:", "text").set_text(newname)
|
||||
win.find("Clone", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
self.app.open(xmleditor_enabled=True)
|
||||
manager = self.app.topwin
|
||||
win = app.manager_open_clone(newname)
|
||||
row = _get_all_rows(win)[0]
|
||||
row.check_in_text(newname)
|
||||
oldnewname = newname
|
||||
newname = "test-aaazzzzbbb"
|
||||
win.find("Name:", "text").set_text(newname)
|
||||
row.select()
|
||||
|
||||
win = self.app.open_details_window("test-clone-simple")
|
||||
win.find("IDE Disk 1", "table cell").click()
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
origpath = "/dev/default-pool/test-clone-simple.img"
|
||||
newpath = tmpsrc.name
|
||||
xmleditor.set_text(xmleditor.text.replace(origpath, newpath))
|
||||
win.find("config-apply").click()
|
||||
win.find("Details", "page tab").click()
|
||||
disksrc = win.find("disk-source-path")
|
||||
lib.utils.check(lambda: disksrc.text == newpath)
|
||||
win.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: not win.active)
|
||||
win.find("Details", "push button").click()
|
||||
stgwin = app.root.find("Change storage path", "dialog")
|
||||
pathtxt = stgwin.find(None, "text", "New Path:")
|
||||
lib.utils.check(lambda: newname in pathtxt.text)
|
||||
stgwin.find("Browse", "push button").click()
|
||||
app.select_storagebrowser_volume("default-pool", "iso-vol")
|
||||
lib.utils.check(lambda: "iso-vol" in pathtxt.text)
|
||||
stgwin.find("OK").click()
|
||||
app.click_alert_button("overwrite the existing", "No")
|
||||
lib.utils.check(lambda: stgwin.showing)
|
||||
stgwin.find("OK").click()
|
||||
app.click_alert_button("overwrite the existing", "Yes")
|
||||
lib.utils.check(lambda: not stgwin.showing)
|
||||
# Can't clone onto existing storage volume
|
||||
win.find("Clone", "push button").click()
|
||||
app.click_alert_button(".*Clone onto existing.*", "Close")
|
||||
|
||||
lib.utils.check(lambda: manager.active)
|
||||
win = self._open_window("test-clone-simple")
|
||||
row = self._get_all_rows(win)[0]
|
||||
row.check_in_text(tmpsrc.name)
|
||||
row.select()
|
||||
# Reopen dialog and request to share it
|
||||
win.find("Details", "push button").click()
|
||||
stgwin = app.root.find("Change storage path", "dialog")
|
||||
chkbox = stgwin.find("Create a new", "check")
|
||||
lib.utils.check(lambda: chkbox.checked)
|
||||
chkbox.click()
|
||||
|
||||
win.find("Details", "push button").click()
|
||||
stgwin = self.app.root.find("Change storage path", "dialog")
|
||||
pathtxt = stgwin.find(None, "text", "New Path:")
|
||||
os.unlink(tmpdst.name)
|
||||
pathtxt.set_text(tmpdst.name)
|
||||
stgwin.find("OK").click()
|
||||
win.find("Clone", "push button").click()
|
||||
lib.utils.check(lambda: not win.active)
|
||||
lib.utils.check(lambda: os.path.exists(tmpdst.name))
|
||||
# Cancel and reopen, confirm changes didn't stick
|
||||
stgwin.find("Cancel").click()
|
||||
lib.utils.check(lambda: not stgwin.showing)
|
||||
win.find("Details", "push button").click()
|
||||
stgwin = app.root.find("Change storage path", "dialog")
|
||||
chkbox = stgwin.find("Create a new", "check")
|
||||
lib.utils.check(lambda: chkbox.checked)
|
||||
# Requesting sharing again and exit
|
||||
chkbox.click()
|
||||
stgwin.find("OK").click()
|
||||
lib.utils.check(lambda: not stgwin.active)
|
||||
|
||||
assert open(tmpsrc.name).read() == open(tmpdst.name).read()
|
||||
# Finish install, verify storage was shared
|
||||
win.find("Clone", "push button").click()
|
||||
app.click_alert_button("cause data to be overwritten", "OK")
|
||||
lib.utils.check(lambda: not win.active)
|
||||
win = app.manager_open_clone(newname)
|
||||
row = _get_all_rows(win)[0].check_in_text(oldnewname)
|
||||
|
||||
|
||||
|
||||
def testCloneError(app):
|
||||
# Trigger some error handling scenarios
|
||||
win = app.manager_open_clone("test-clone-full")
|
||||
win.find("Clone", "push button").click()
|
||||
app.click_alert_button("not enough free space", "Close")
|
||||
lib.utils.check(lambda: win.showing)
|
||||
win.keyCombo("<alt>F4")
|
||||
|
||||
win = app.manager_open_clone("test-clone-simple")
|
||||
badname = "test/foo"
|
||||
win.find("Name:", "text").set_text(badname)
|
||||
rows = _get_all_rows(win)
|
||||
rows[0].chkcell.click()
|
||||
rows[0].check_in_text("Share disk with")
|
||||
win.find("Clone", "push button").click()
|
||||
win.find("Clone", "push button").click()
|
||||
app.click_alert_button("cause data to be overwritten", "OK")
|
||||
app.click_alert_button(badname, "Close")
|
||||
lib.utils.check(lambda: win.active)
|
||||
|
||||
|
||||
|
||||
def testCloneNonmanaged(app):
|
||||
# Verify unmanaged clone actual works
|
||||
import tempfile
|
||||
tmpsrc = tempfile.NamedTemporaryFile()
|
||||
tmpdst = tempfile.NamedTemporaryFile()
|
||||
|
||||
open(tmpsrc.name, "w").write(__file__)
|
||||
|
||||
app.open(xmleditor_enabled=True)
|
||||
manager = app.topwin
|
||||
|
||||
win = app.manager_open_details("test-clone-simple")
|
||||
win.find("IDE Disk 1", "table cell").click()
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
origpath = "/dev/default-pool/test-clone-simple.img"
|
||||
newpath = tmpsrc.name
|
||||
xmleditor.set_text(xmleditor.text.replace(origpath, newpath))
|
||||
win.find("config-apply").click()
|
||||
win.find("Details", "page tab").click()
|
||||
disksrc = win.find("disk-source-path")
|
||||
lib.utils.check(lambda: disksrc.text == newpath)
|
||||
win.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: not win.active)
|
||||
|
||||
lib.utils.check(lambda: manager.active)
|
||||
win = app.manager_open_clone("test-clone-simple")
|
||||
row = _get_all_rows(win)[0]
|
||||
row.check_in_text(tmpsrc.name)
|
||||
row.select()
|
||||
|
||||
win.find("Details", "push button").click()
|
||||
stgwin = app.root.find("Change storage path", "dialog")
|
||||
pathtxt = stgwin.find(None, "text", "New Path:")
|
||||
os.unlink(tmpdst.name)
|
||||
pathtxt.set_text(tmpdst.name)
|
||||
stgwin.find("OK").click()
|
||||
win.find("Clone", "push button").click()
|
||||
lib.utils.check(lambda: not win.active)
|
||||
lib.utils.check(lambda: os.path.exists(tmpdst.name))
|
||||
|
||||
assert open(tmpsrc.name).read() == open(tmpdst.name).read()
|
||||
|
|
|
@ -4,109 +4,97 @@
|
|||
from . import lib
|
||||
|
||||
|
||||
class UITestConnection(lib.testcase.UITestCase):
|
||||
"""
|
||||
UI tests for various connection.py related bits
|
||||
"""
|
||||
###################################################
|
||||
# UI tests for various connection.py related bits #
|
||||
###################################################
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
def testConnectionBlacklist(app):
|
||||
app.open(
|
||||
extra_opts=["--test-options=object-blacklist=test-many-devices"])
|
||||
manager = app.topwin
|
||||
|
||||
def testConnectionBlacklist(self):
|
||||
self.app.open(
|
||||
extra_opts=["--test-options=object-blacklist=test-many-devices"])
|
||||
manager = self.app.topwin
|
||||
|
||||
def _delete_vm(vmname):
|
||||
cell = manager.find(vmname, "table cell")
|
||||
cell.click()
|
||||
cell.click(button=3)
|
||||
menu = self.app.root.find("vm-action-menu")
|
||||
menu.find("Delete", "menu item").click()
|
||||
delete = self.app.root.find_fuzzy("Delete", "frame")
|
||||
delete.find("Delete associated", "check box").click()
|
||||
delete.find("Delete", "push button").click()
|
||||
lib.utils.check(lambda: cell.dead)
|
||||
lib.utils.check(lambda: manager.active)
|
||||
|
||||
lib.utils.check(
|
||||
lambda: "test-many-devices" not in self.app.topwin.fmt_nodes())
|
||||
_delete_vm("test-arm-kernel")
|
||||
_delete_vm("test alternate")
|
||||
_delete_vm("test-clone-simple")
|
||||
self.app.sleep(.5)
|
||||
lib.utils.check(
|
||||
lambda: "test-many-devices" not in self.app.topwin.fmt_nodes())
|
||||
|
||||
def testConnectionConnCrash(self):
|
||||
self.app.open(
|
||||
extra_opts=["--test-options=conn-crash"])
|
||||
manager = self.app.topwin
|
||||
|
||||
self.app.sleep(1)
|
||||
manager.find(r"^test testdriver.xml - Not Connected", "table cell")
|
||||
def _delete_vm(vmname):
|
||||
app.manager_vm_action(vmname, delete=True)
|
||||
delete = app.find_window("Delete")
|
||||
delete.find("Delete associated", "check box").click()
|
||||
delete.find("Delete", "push button").click()
|
||||
lib.utils.check(lambda: manager.active)
|
||||
|
||||
def testConnectionFakeEvents(self):
|
||||
self.app.open(
|
||||
extra_opts=["--test-options=fake-nodedev-event=computer",
|
||||
"--test-options=fake-agent-event=test-many-devices"])
|
||||
manager = self.app.topwin
|
||||
self.app.sleep(2.5)
|
||||
lib.utils.check(lambda: manager.active)
|
||||
|
||||
def testConnectionOpenauth(self):
|
||||
self.app.open(
|
||||
extra_opts=["--test-options=fake-openauth"],
|
||||
window_name="Authentication required")
|
||||
|
||||
dialog = self.app.root.find("Authentication required")
|
||||
def _run():
|
||||
username = dialog.find("Username:.*entry")
|
||||
password = dialog.find("Password:.*entry")
|
||||
username.click()
|
||||
username.text = "foo"
|
||||
self.app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: password.focused)
|
||||
password.typeText("bar")
|
||||
lib.utils.check(
|
||||
lambda: "test-many-devices" not in app.topwin.fmt_nodes())
|
||||
_delete_vm("test-arm-kernel")
|
||||
_delete_vm("test-clone-full")
|
||||
_delete_vm("test-clone-simple")
|
||||
app.sleep(.5)
|
||||
lib.utils.check(
|
||||
lambda: "test-many-devices" not in app.topwin.fmt_nodes())
|
||||
|
||||
|
||||
_run()
|
||||
dialog.find("OK", "push button").click()
|
||||
lib.utils.check(lambda: not dialog.showing)
|
||||
manager = self.app.root.find("Virtual Machine Manager", "frame")
|
||||
manager.find("^test testdriver.xml$", "table cell")
|
||||
def testConnectionConnCrash(app):
|
||||
app.open(
|
||||
extra_opts=["--test-options=conn-crash"])
|
||||
manager = app.topwin
|
||||
|
||||
# Disconnect and reconnect to trigger it again
|
||||
def _retrigger_connection():
|
||||
manager.click()
|
||||
c = manager.find_fuzzy("testdriver.xml", "table cell")
|
||||
c.click()
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-disconnect", "menu item").click()
|
||||
manager.click()
|
||||
c = manager.find_fuzzy("testdriver.xml", "table cell")
|
||||
c.click()
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-connect", "menu item").click()
|
||||
app.sleep(1)
|
||||
manager.find(r"^test testdriver.xml - Not Connected", "table cell")
|
||||
lib.utils.check(lambda: manager.active)
|
||||
|
||||
_retrigger_connection()
|
||||
dialog = self.app.root.find("Authentication required")
|
||||
_run()
|
||||
self.app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: not dialog.showing)
|
||||
manager = self.app.root.find("Virtual Machine Manager", "frame")
|
||||
manager.find("^test testdriver.xml$", "table cell")
|
||||
|
||||
_retrigger_connection()
|
||||
dialog = self.app.root.find("Authentication required")
|
||||
dialog.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not dialog.showing)
|
||||
self.app.click_alert_button("Unable to connect", "Close")
|
||||
manager.find("test testdriver.xml - Not Connected", "table cell")
|
||||
def testConnectionFakeEvents(app):
|
||||
app.open(
|
||||
extra_opts=["--test-options=fake-nodedev-event=computer",
|
||||
"--test-options=fake-agent-event=test-many-devices"])
|
||||
manager = app.topwin
|
||||
app.sleep(2.5)
|
||||
lib.utils.check(lambda: manager.active)
|
||||
|
||||
def testConnectionSessionError(self):
|
||||
self.app.open(
|
||||
extra_opts=["--test-options=fake-session-error"])
|
||||
self.app.click_alert_button("Could not detect a local session", "Close")
|
||||
|
||||
def testConnectionOpenauth(app):
|
||||
app.open(
|
||||
extra_opts=["--test-options=fake-openauth"],
|
||||
window_name="Authentication required")
|
||||
|
||||
dialog = app.root.find("Authentication required")
|
||||
def _run():
|
||||
username = dialog.find("Username:.*entry")
|
||||
password = dialog.find("Password:.*entry")
|
||||
username.click()
|
||||
username.text = "foo"
|
||||
app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: password.focused)
|
||||
password.typeText("bar")
|
||||
|
||||
|
||||
_run()
|
||||
dialog.find("OK", "push button").click()
|
||||
lib.utils.check(lambda: not dialog.showing)
|
||||
manager = app.find_window("Virtual Machine Manager")
|
||||
manager.find("^test testdriver.xml$", "table cell")
|
||||
|
||||
# Disconnect and reconnect to trigger it again
|
||||
def _retrigger_connection():
|
||||
manager.click()
|
||||
app.manager_conn_disconnect("test testdriver.xml")
|
||||
manager.click()
|
||||
app.manager_conn_connect("test testdriver.xml")
|
||||
|
||||
_retrigger_connection()
|
||||
dialog = app.root.find("Authentication required")
|
||||
_run()
|
||||
app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: not dialog.showing)
|
||||
manager = app.find_window("Virtual Machine Manager")
|
||||
manager.find("^test testdriver.xml$", "table cell")
|
||||
|
||||
_retrigger_connection()
|
||||
dialog = app.root.find("Authentication required")
|
||||
dialog.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not dialog.showing)
|
||||
app.click_alert_button("Unable to connect", "Close")
|
||||
manager.find("test testdriver.xml - Not Connected", "table cell")
|
||||
|
||||
|
||||
def testConnectionSessionError(app):
|
||||
app.open(
|
||||
extra_opts=["--test-options=fake-session-error"])
|
||||
app.click_alert_button("Could not detect a local session", "Close")
|
||||
|
|
|
@ -4,144 +4,100 @@
|
|||
from . import lib
|
||||
|
||||
|
||||
class VMMConnect(lib.testcase.UITestCase):
|
||||
"""
|
||||
UI tests for the 'open connection' dialog
|
||||
"""
|
||||
#############################################
|
||||
# UI tests for the 'open connection' dialog #
|
||||
#############################################
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
|
||||
def testConnect(self):
|
||||
# Start with connection delete
|
||||
c = self.app.root.find("test testdriver.xml", "table cell")
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-disconnect", "menu item").click()
|
||||
lib.utils.check(lambda: "Not Connected" in c.text)
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-delete", "menu item").click()
|
||||
self.app.click_alert_button("will remove the connection", "No")
|
||||
lib.utils.check(lambda: not c.dead)
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-delete", "menu item").click()
|
||||
self.app.click_alert_button("will remove the connection", "Yes")
|
||||
lib.utils.check(lambda: c.dead)
|
||||
def testConnect(app):
|
||||
# Start with connection delete
|
||||
c = app.manager_conn_disconnect("test testdriver.xml")
|
||||
c.click(button=3)
|
||||
app.root.find("conn-delete", "menu item").click()
|
||||
app.click_alert_button("will remove the connection", "No")
|
||||
lib.utils.check(lambda: not c.dead)
|
||||
app.manager_conn_delete("test testdriver.xml")
|
||||
|
||||
# Launch the dialog, grab some UI pointers
|
||||
self.app.root.find("File", "menu").click()
|
||||
self.app.root.find("Add Connection...", "menu item").click()
|
||||
win = self.app.root.find_fuzzy("Add Connection", "dialog")
|
||||
# Launch the dialog, grab some UI pointers
|
||||
win = app.manager_open_createconn()
|
||||
connect = win.find("Connect", "push button")
|
||||
remote = win.find_fuzzy("Connect to remote", "check box")
|
||||
user = win.find("Username", "text")
|
||||
host = win.find("Hostname", "text")
|
||||
urilabel = win.find("uri-label", "label")
|
||||
lib.utils.check(lambda: user.showing is host.showing is True)
|
||||
|
||||
connect = win.find("Connect", "push button")
|
||||
remote = win.find_fuzzy("Connect to remote", "check box")
|
||||
user = win.find("Username", "text")
|
||||
host = win.find("Hostname", "text")
|
||||
urilabel = win.find("uri-label", "label")
|
||||
urientry = win.find("uri-entry", "text")
|
||||
lib.utils.check(lambda: user.showing is host.showing is True)
|
||||
# Select all HV options
|
||||
win.combo_select("Hypervisor", "QEMU/KVM user session")
|
||||
win.combo_select("Hypervisor", r"^QEMU/KVM$")
|
||||
win.combo_select("Hypervisor", "Xen")
|
||||
win.combo_select("Hypervisor", "Bhyve")
|
||||
win.combo_select("Hypervisor", "Virtuozzo")
|
||||
win.combo_select("Hypervisor", r".*LXC.*")
|
||||
|
||||
# Select all HV options
|
||||
win.combo_select("Hypervisor", "QEMU/KVM user session")
|
||||
win.combo_select("Hypervisor", r"^QEMU/KVM$")
|
||||
win.combo_select("Hypervisor", "Xen")
|
||||
win.combo_select("Hypervisor", "Bhyve")
|
||||
win.combo_select("Hypervisor", "Virtuozzo")
|
||||
win.combo_select("Hypervisor", r".*LXC.*")
|
||||
# Test a simple selection
|
||||
win.combo_select("Hypervisor", "QEMU/KVM user session")
|
||||
lib.utils.check(lambda: user.showing is host.showing is False)
|
||||
lib.utils.check(lambda: urilabel.text == "qemu:///session")
|
||||
|
||||
# Test a simple selection
|
||||
win.combo_select("Hypervisor", "QEMU/KVM user session")
|
||||
lib.utils.check(lambda: user.showing is host.showing is False)
|
||||
lib.utils.check(lambda: urilabel.text == "qemu:///session")
|
||||
# Cancel the dialog
|
||||
win.find_fuzzy("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
# Cancel the dialog
|
||||
win.find_fuzzy("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
# Reopen it, confirm content changed
|
||||
win = app.manager_open_createconn()
|
||||
lib.utils.check(lambda: ":///session" not in urilabel.text)
|
||||
|
||||
# Reopen it, confirm content changed
|
||||
self.app.root.find("File", "menu").click()
|
||||
self.app.root.find("Add Connection...", "menu item").click()
|
||||
win = self.app.root.find_fuzzy("Add Connection", "dialog")
|
||||
lib.utils.check(lambda: ":///session" not in urilabel.text)
|
||||
# Relaunch the dialog, confirm it doesn't overwrite content
|
||||
win.combo_select("Hypervisor", ".*LXC.*")
|
||||
lib.utils.check(lambda: "lxc" in urilabel.text)
|
||||
win = app.manager_open_createconn()
|
||||
lib.utils.check(lambda: win.active)
|
||||
lib.utils.check(lambda: "lxc" in urilabel.text)
|
||||
|
||||
# Relaunch the dialog, confirm it doesn't overwrite content
|
||||
win.combo_select("Hypervisor", ".*LXC.*")
|
||||
lib.utils.check(lambda: "lxc" in urilabel.text)
|
||||
self.app.root.find("File", "menu").click()
|
||||
self.app.root.find("Add Connection...", "menu item").click()
|
||||
lib.utils.check(lambda: win.active)
|
||||
lib.utils.check(lambda: "lxc" in urilabel.text)
|
||||
# Enter a failing URI, make sure error is raised, and we can
|
||||
# fall back to the dialog
|
||||
win.combo_select("Hypervisor", "Xen")
|
||||
remote.click()
|
||||
user.set_text("fribuser")
|
||||
connect.click()
|
||||
app.click_alert_button("hostname is required", "OK")
|
||||
fakeipv6 = "fe80::1"
|
||||
host.set_text(fakeipv6)
|
||||
lib.utils.check(lambda: urilabel.text == "xen+ssh://fribuser@[%s]/" % fakeipv6)
|
||||
fakehost = "ix8khfyidontexistkdjur.com"
|
||||
host.set_text(fakehost + ":12345")
|
||||
lib.utils.check(lambda: urilabel.text == "xen+ssh://fribuser@%s:12345/" % fakehost)
|
||||
connect.click()
|
||||
|
||||
# Enter a failing URI, make sure error is raised, and we can
|
||||
# fall back to the dialog
|
||||
win.combo_select("Hypervisor", "Xen")
|
||||
remote.click()
|
||||
user.set_text("fribuser")
|
||||
connect.click()
|
||||
self.app.click_alert_button("hostname is required", "OK")
|
||||
fakeipv6 = "fe80::1"
|
||||
host.set_text(fakeipv6)
|
||||
lib.utils.check(lambda: urilabel.text == "xen+ssh://fribuser@[%s]/" % fakeipv6)
|
||||
fakehost = "ix8khfyidontexistkdjur.com"
|
||||
host.set_text(fakehost + ":12345")
|
||||
lib.utils.check(lambda: urilabel.text == "xen+ssh://fribuser@%s:12345/" % fakehost)
|
||||
connect.click()
|
||||
lib.utils.check(lambda: win.showing is True)
|
||||
c = app.root.find_fuzzy(fakehost, "table cell")
|
||||
lib.utils.check(lambda: "Connecting..." not in c.text, timeout=10)
|
||||
app.click_alert_button("Unable to connect", "No")
|
||||
|
||||
lib.utils.check(lambda: win.showing is True)
|
||||
c = self.app.root.find_fuzzy(fakehost, "table cell")
|
||||
lib.utils.check(lambda: "Connecting..." not in c.text, timeout=10)
|
||||
self.app.click_alert_button("Unable to connect", "No")
|
||||
# Ensure dialog shows old contents for editing
|
||||
lib.utils.check(lambda: win.showing)
|
||||
lib.utils.check(lambda: fakehost in host.text)
|
||||
|
||||
# Ensure dialog shows old contents for editing
|
||||
lib.utils.check(lambda: win.showing)
|
||||
lib.utils.check(lambda: fakehost in host.text)
|
||||
# This time say 'yes'
|
||||
connect.click()
|
||||
lib.utils.check(lambda: win.showing is True)
|
||||
c = app.root.find_fuzzy(fakehost, "table cell")
|
||||
lib.utils.check(lambda: "Connecting..." not in c.text, timeout=10)
|
||||
app.click_alert_button("Unable to connect", "Yes")
|
||||
c = app.root.find_fuzzy(fakehost, "table cell")
|
||||
lib.utils.check(lambda: win.showing is False)
|
||||
|
||||
# This time say 'yes'
|
||||
connect.click()
|
||||
lib.utils.check(lambda: win.showing is True)
|
||||
c = self.app.root.find_fuzzy(fakehost, "table cell")
|
||||
lib.utils.check(lambda: "Connecting..." not in c.text, timeout=10)
|
||||
self.app.click_alert_button("Unable to connect", "Yes")
|
||||
c = self.app.root.find_fuzzy(fakehost, "table cell")
|
||||
# Test with custom test:///default connection
|
||||
app.manager_createconn("test:///default")
|
||||
# Do it again to make sure things don't explode
|
||||
app.manager_createconn("test:///default")
|
||||
|
||||
# Test with custom test:///default connection
|
||||
lib.utils.check(lambda: win.showing is False)
|
||||
self.app.root.find("File", "menu").click()
|
||||
self.app.root.find("Add Connection...", "menu item").click()
|
||||
win = self.app.root.find_fuzzy("Add Connection", "dialog")
|
||||
win.combo_select("Hypervisor", "Custom URI")
|
||||
urientry.set_text("test:///default")
|
||||
connect.click()
|
||||
# Test connection double click
|
||||
c = app.manager_conn_disconnect("test default")
|
||||
c.doubleClick()
|
||||
lib.utils.check(lambda: "Not Connected" not in c.text)
|
||||
|
||||
# Do it again to make sure things don't explode
|
||||
lib.utils.check(lambda: win.showing is False)
|
||||
self.app.root.find("File", "menu").click()
|
||||
self.app.root.find("Add Connection...", "menu item").click()
|
||||
win = self.app.root.find_fuzzy("Add Connection", "dialog")
|
||||
win.combo_select("Hypervisor", "Custom URI")
|
||||
urientry.set_text("test:///default")
|
||||
connect.click()
|
||||
|
||||
# Try various connect/disconnect routines
|
||||
lib.utils.check(lambda: win.showing is False)
|
||||
c = self.app.root.find("test default", "table cell")
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-disconnect", "menu item").click()
|
||||
lib.utils.check(lambda: "Not Connected" in c.text)
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-connect", "menu item").click()
|
||||
c = self.app.root.find("test default", "table cell")
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-disconnect", "menu item").click()
|
||||
lib.utils.check(lambda: "Not Connected" in c.text)
|
||||
c.doubleClick()
|
||||
c = self.app.root.find("test default", "table cell")
|
||||
c.click()
|
||||
# Delete it
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-disconnect", "menu item").click()
|
||||
lib.utils.check(lambda: "Not Connected" in c.text)
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-delete", "menu item").click()
|
||||
self.app.click_alert_button("will remove the connection", "Yes")
|
||||
lib.utils.check(lambda: c.dead)
|
||||
# Delete it
|
||||
app.manager_conn_disconnect("test default")
|
||||
app.manager_conn_delete("test default")
|
||||
|
|
|
@ -4,169 +4,166 @@
|
|||
from . import lib
|
||||
|
||||
|
||||
class CreateNet(lib.testcase.UITestCase):
|
||||
#####################################
|
||||
# UI tests for the createnet wizard #
|
||||
#####################################
|
||||
|
||||
def _open_netadd(app, hostwin):
|
||||
hostwin.find("net-add", "push button").click()
|
||||
win = app.find_window("Create a new virtual network")
|
||||
return win
|
||||
|
||||
|
||||
def testCreateNet(app):
|
||||
"""
|
||||
UI tests for the createnet wizard
|
||||
Basic test with object state management afterwards
|
||||
"""
|
||||
hostwin = app.manager_open_host("Virtual Networks")
|
||||
win = _open_netadd(app, hostwin)
|
||||
|
||||
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
|
||||
# Create a simple default network
|
||||
name = win.find("Name:", "text")
|
||||
finish = win.find("Finish", "push button")
|
||||
lib.utils.check(lambda: name.text == "network")
|
||||
newname = "a-test-new-net"
|
||||
name.set_text(newname)
|
||||
finish.click()
|
||||
|
||||
# Select the new network in the host window, then do
|
||||
# stop->start->stop->delete, for lifecycle testing
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
cell = hostwin.find(newname, "table cell")
|
||||
delete = hostwin.find("net-delete", "push button")
|
||||
start = hostwin.find("net-start", "push button")
|
||||
stop = hostwin.find("net-stop", "push button")
|
||||
|
||||
cell.click()
|
||||
stop.click()
|
||||
lib.utils.check(lambda: start.sensitive)
|
||||
start.click()
|
||||
lib.utils.check(lambda: stop.sensitive)
|
||||
stop.click()
|
||||
lib.utils.check(lambda: delete.sensitive)
|
||||
|
||||
# Delete it, clicking No first
|
||||
delete.click()
|
||||
app.click_alert_button("permanently delete the network", "No")
|
||||
lib.utils.check(lambda: not cell.dead)
|
||||
delete.click()
|
||||
app.click_alert_button("permanently delete the network", "Yes")
|
||||
# Ensure it's gone
|
||||
lib.utils.check(lambda: cell.dead)
|
||||
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
|
||||
def testCreateNet(self):
|
||||
"""
|
||||
Basic test with object state management afterwards
|
||||
"""
|
||||
hostwin = self.app.open_host_window("Virtual Networks")
|
||||
win = self._open_create_win(hostwin)
|
||||
def testCreateNetXMLEditor(app):
|
||||
"""
|
||||
Test the XML editor
|
||||
"""
|
||||
app.open(xmleditor_enabled=True)
|
||||
hostwin = app.manager_open_host("Virtual Networks")
|
||||
win = _open_netadd(app, hostwin)
|
||||
name = win.find("Name:", "text")
|
||||
finish = win.find("Finish", "push button")
|
||||
|
||||
# Create a simple default network
|
||||
name = win.find("Name:", "text")
|
||||
finish = win.find("Finish", "push button")
|
||||
lib.utils.check(lambda: name.text == "network")
|
||||
newname = "a-test-new-net"
|
||||
name.set_text(newname)
|
||||
finish.click()
|
||||
# Create a new obj with XML edited name, verify it worked
|
||||
tmpname = "objtmpname"
|
||||
newname = "froofroo"
|
||||
name.set_text(tmpname)
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
newtext = xmleditor.text.replace(">%s<" % tmpname, ">%s<" % newname)
|
||||
xmleditor.set_text(newtext)
|
||||
finish.click()
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
cell = hostwin.find(newname, "table cell")
|
||||
cell.click()
|
||||
|
||||
# Select the new network in the host window, then do
|
||||
# stop->start->stop->delete, for lifecycle testing
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
cell = hostwin.find(newname, "table cell")
|
||||
delete = hostwin.find("net-delete", "push button")
|
||||
start = hostwin.find("net-start", "push button")
|
||||
stop = hostwin.find("net-stop", "push button")
|
||||
# Do standard xmleditor tests
|
||||
win = _open_netadd(app, hostwin)
|
||||
lib.utils.test_xmleditor_interactions(app, win, finish)
|
||||
win.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.visible)
|
||||
|
||||
cell.click()
|
||||
stop.click()
|
||||
lib.utils.check(lambda: start.sensitive)
|
||||
start.click()
|
||||
lib.utils.check(lambda: stop.sensitive)
|
||||
stop.click()
|
||||
lib.utils.check(lambda: delete.sensitive)
|
||||
|
||||
# Delete it, clicking No first
|
||||
delete.click()
|
||||
self.app.click_alert_button("permanently delete the network", "No")
|
||||
lib.utils.check(lambda: not cell.dead)
|
||||
delete.click()
|
||||
self.app.click_alert_button("permanently delete the network", "Yes")
|
||||
# Ensure it's gone
|
||||
lib.utils.check(lambda: cell.dead)
|
||||
# Ensure host window closes fine
|
||||
hostwin.click()
|
||||
hostwin.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: not hostwin.showing and
|
||||
not hostwin.active)
|
||||
|
||||
|
||||
def testCreateNetXMLEditor(self):
|
||||
"""
|
||||
Test the XML editor
|
||||
"""
|
||||
self.app.open(xmleditor_enabled=True)
|
||||
hostwin = self.app.open_host_window("Virtual Networks")
|
||||
win = self._open_create_win(hostwin)
|
||||
name = win.find("Name:", "text")
|
||||
finish = win.find("Finish", "push button")
|
||||
def testCreateNetMulti(app):
|
||||
"""
|
||||
Test remaining create options
|
||||
"""
|
||||
app.uri = "test:///default"
|
||||
hostwin = app.manager_open_host(
|
||||
"Virtual Networks", conn_label="test default")
|
||||
win = _open_netadd(app, hostwin)
|
||||
finish = win.find("Finish", "push button")
|
||||
|
||||
# Create a new obj with XML edited name, verify it worked
|
||||
tmpname = "objtmpname"
|
||||
newname = "froofroo"
|
||||
name.set_text(tmpname)
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
newtext = xmleditor.text.replace(">%s<" % tmpname, ">%s<" % newname)
|
||||
xmleditor.set_text(newtext)
|
||||
finish.click()
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
cell = hostwin.find(newname, "table cell")
|
||||
cell.click()
|
||||
# Create a network with a bunch of options
|
||||
win.find("Name:", "text").set_text("default")
|
||||
win.find("net-mode").click()
|
||||
win.find("Isolated", "menu item").click()
|
||||
win.find("IPv4 configuration").click_expander()
|
||||
win.find("ipv4-network").set_text("192.168.100.0/25")
|
||||
ipv4start = win.find("ipv4-start")
|
||||
ipv4end = win.find("ipv4-end")
|
||||
lib.utils.check(lambda: ipv4start.text == "192.168.100.64")
|
||||
lib.utils.check(lambda: ipv4end.text == "192.168.100.126")
|
||||
win.find("Enable DHCPv4").click()
|
||||
win.find("Enable IPv4").click()
|
||||
win.find("IPv6 configuration").click_expander()
|
||||
win.find("Enable IPv6").click()
|
||||
win.find("Enable DHCPv6").click()
|
||||
win.find("ipv6-network").set_text("fd00:beef:10:6::1/64")
|
||||
win.find("ipv6-start").set_text("fd00:beef:10:6::1:1")
|
||||
win.find("ipv6-end").set_text("bad")
|
||||
win.find("DNS domain name").click_expander()
|
||||
win.find("Custom").click()
|
||||
win.find("domain-custom").set_text("mydomain")
|
||||
finish.click()
|
||||
# Name collision validation
|
||||
app.click_alert_button("in use by another network", "Close")
|
||||
win.find("Name:", "text").set_text("newnet1")
|
||||
finish.click()
|
||||
# XML define error
|
||||
app.click_alert_button("Error creating virtual network", "Close")
|
||||
win.find("ipv6-end").set_text("fd00:beef:10:6::1:f1")
|
||||
finish.click()
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
|
||||
# Do standard xmleditor tests
|
||||
win = self._open_create_win(hostwin)
|
||||
lib.utils.test_xmleditor_interactions(self.app, win, finish)
|
||||
win.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.visible)
|
||||
# More option work
|
||||
win = _open_netadd(app, hostwin)
|
||||
win.find("Name:", "text").set_text("newnet2")
|
||||
devicelist = win.find("net-devicelist")
|
||||
lib.utils.check(lambda: not devicelist.visible)
|
||||
win.find("net-mode").click()
|
||||
win.find("SR-IOV", "menu item").click()
|
||||
lib.utils.check(lambda: devicelist.visible)
|
||||
# Just confirm this is here
|
||||
win.find("No available device", "menu item")
|
||||
win.find("net-mode").click()
|
||||
win.find("Routed", "menu item").click()
|
||||
win.find("net-forward").click()
|
||||
win.find("Physical device", "menu item").click()
|
||||
win.find("net-device").set_text("fakedev0")
|
||||
finish.click()
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
|
||||
# Ensure host window closes fine
|
||||
hostwin.click()
|
||||
hostwin.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: not hostwin.showing and
|
||||
not hostwin.active)
|
||||
|
||||
def testCreateNetMulti(self):
|
||||
"""
|
||||
Test remaining create options
|
||||
"""
|
||||
self.app.uri = "test:///default"
|
||||
hostwin = self.app.open_host_window(
|
||||
"Virtual Networks", conn_label="test default")
|
||||
win = self._open_create_win(hostwin)
|
||||
finish = win.find("Finish", "push button")
|
||||
def testCreateNetSRIOV(app):
|
||||
"""
|
||||
We need the full URI to test the SRIOV method
|
||||
"""
|
||||
app.open(xmleditor_enabled=True)
|
||||
hostwin = app.manager_open_host("Virtual Networks")
|
||||
win = _open_netadd(app, hostwin)
|
||||
finish = win.find("Finish", "push button")
|
||||
|
||||
# Create a network with a bunch of options
|
||||
win.find("Name:", "text").set_text("default")
|
||||
win.find("net-mode").click()
|
||||
win.find("Isolated", "menu item").click()
|
||||
win.find("IPv4 configuration").click_expander()
|
||||
win.find("ipv4-network").set_text("192.168.100.0/25")
|
||||
ipv4start = win.find("ipv4-start")
|
||||
ipv4end = win.find("ipv4-end")
|
||||
lib.utils.check(lambda: ipv4start.text == "192.168.100.64")
|
||||
lib.utils.check(lambda: ipv4end.text == "192.168.100.126")
|
||||
win.find("Enable DHCPv4").click()
|
||||
win.find("Enable IPv4").click()
|
||||
win.find("IPv6 configuration").click_expander()
|
||||
win.find("Enable IPv6").click()
|
||||
win.find("Enable DHCPv6").click()
|
||||
win.find("ipv6-network").set_text("fd00:beef:10:6::1/64")
|
||||
win.find("ipv6-start").set_text("fd00:beef:10:6::1:1")
|
||||
win.find("ipv6-end").set_text("bad")
|
||||
win.find("DNS domain name").click_expander()
|
||||
win.find("Custom").click()
|
||||
win.find("domain-custom").set_text("mydomain")
|
||||
finish.click()
|
||||
# Name collision validation
|
||||
self.app.click_alert_button("in use by another network", "Close")
|
||||
win.find("Name:", "text").set_text("newnet1")
|
||||
finish.click()
|
||||
# XML define error
|
||||
self.app.click_alert_button("Error creating virtual network", "Close")
|
||||
win.find("ipv6-end").set_text("fd00:beef:10:6::1:f1")
|
||||
finish.click()
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
|
||||
# More option work
|
||||
win = self._open_create_win(hostwin)
|
||||
win.find("Name:", "text").set_text("newnet2")
|
||||
devicelist = win.find("net-devicelist")
|
||||
lib.utils.check(lambda: not devicelist.visible)
|
||||
win.find("net-mode").click()
|
||||
win.find("SR-IOV", "menu item").click()
|
||||
lib.utils.check(lambda: devicelist.visible)
|
||||
# Just confirm this is here
|
||||
win.find("No available device", "menu item")
|
||||
win.find("net-mode").click()
|
||||
win.find("Routed", "menu item").click()
|
||||
win.find("net-forward").click()
|
||||
win.find("Physical device", "menu item").click()
|
||||
win.find("net-device").set_text("fakedev0")
|
||||
finish.click()
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
|
||||
def testCreateNetSRIOV(self):
|
||||
"""
|
||||
We need the full URI to test the SRIOV method
|
||||
"""
|
||||
self.app.open(xmleditor_enabled=True)
|
||||
hostwin = self.app.open_host_window("Virtual Networks")
|
||||
win = self._open_create_win(hostwin)
|
||||
finish = win.find("Finish", "push button")
|
||||
|
||||
win.find("net-mode").click()
|
||||
win.find("SR-IOV", "menu item").click()
|
||||
win.find("net-devicelist").click()
|
||||
win.find_fuzzy("eth3", "menu item").click()
|
||||
finish.click()
|
||||
win.find("net-mode").click()
|
||||
win.find("SR-IOV", "menu item").click()
|
||||
win.find("net-devicelist").click()
|
||||
win.find_fuzzy("eth3", "menu item").click()
|
||||
finish.click()
|
||||
|
|
|
@ -4,157 +4,152 @@
|
|||
from . import lib
|
||||
|
||||
|
||||
class CreatePool(lib.testcase.UITestCase):
|
||||
"""
|
||||
UI tests for the createpool wizard
|
||||
"""
|
||||
######################################
|
||||
# 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")
|
||||
def _open_createpool(app, hostwin):
|
||||
hostwin.find("pool-add", "push button").click()
|
||||
win = app.find_window("Add a New Storage Pool")
|
||||
lib.utils.check(lambda: win.active)
|
||||
return win
|
||||
|
||||
|
||||
def testCreatePools(app):
|
||||
hostwin = app.manager_open_host("Storage")
|
||||
win = _open_createpool(app, hostwin)
|
||||
finish = win.find("Finish", "push button")
|
||||
name = win.find("Name:", "text")
|
||||
|
||||
def _browse_local_path(winlabel, usepath):
|
||||
chooser = app.root.find(winlabel, "file chooser")
|
||||
# Enter the filename and select it
|
||||
chooser.find(usepath, "table cell").click()
|
||||
obutton = chooser.find("Open", "push button")
|
||||
lib.utils.check(lambda: obutton.sensitive)
|
||||
obutton.click()
|
||||
lib.utils.check(lambda: not chooser.showing)
|
||||
lib.utils.check(lambda: win.active)
|
||||
return win
|
||||
|
||||
# Create a simple default dir pool
|
||||
lib.utils.check(lambda: name.text == "pool")
|
||||
newname = "a-test-new-pool"
|
||||
name.set_text(newname)
|
||||
finish.click()
|
||||
|
||||
# Select the new object in the host window, then do
|
||||
# stop->start->stop->delete, for lifecycle testing
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
cell = hostwin.find(newname, "table cell")
|
||||
delete = hostwin.find("pool-delete", "push button")
|
||||
start = hostwin.find("pool-start", "push button")
|
||||
stop = hostwin.find("pool-stop", "push button")
|
||||
|
||||
cell.click()
|
||||
stop.click()
|
||||
lib.utils.check(lambda: start.sensitive)
|
||||
start.click()
|
||||
lib.utils.check(lambda: stop.sensitive)
|
||||
stop.click()
|
||||
lib.utils.check(lambda: delete.sensitive)
|
||||
|
||||
# Delete it, clicking 'No' first
|
||||
delete.click()
|
||||
app.click_alert_button("permanently delete the pool", "No")
|
||||
lib.utils.check(lambda: not cell.dead)
|
||||
delete.click()
|
||||
app.click_alert_button("permanently delete the pool", "Yes")
|
||||
# Ensure it's gone
|
||||
lib.utils.check(lambda: cell.dead)
|
||||
|
||||
# Test a disk pool
|
||||
win = _open_createpool(app, hostwin)
|
||||
win.combo_select("Type:", "disk:")
|
||||
newname = "a-disk-pool"
|
||||
name.set_text("a-disk-pool")
|
||||
win.find("source-browse").click()
|
||||
_browse_local_path("Choose source path", "console")
|
||||
finish.click()
|
||||
hostwin.find(newname, "table cell")
|
||||
|
||||
# Test a iscsi pool
|
||||
win = _open_createpool(app, hostwin)
|
||||
win.combo_select("Type:", "iscsi:")
|
||||
newname = "a-iscsi-pool"
|
||||
name.set_text("a-iscsi-pool")
|
||||
win.find("target-browse").click()
|
||||
_browse_local_path("Choose target directory", "by-path")
|
||||
finish.click()
|
||||
# Catch example error
|
||||
app.click_alert_button("source host name", "Close")
|
||||
win.find("Host Name:", "text").set_text("example.com")
|
||||
win.find("pool-source-path-text").set_text("foo-iqn")
|
||||
win.find_fuzzy("Initiator IQN:", "check").click()
|
||||
win.find("iqn-text", "text").set_text("initiator-foo")
|
||||
finish.click()
|
||||
hostwin.find(newname, "table cell")
|
||||
|
||||
# Test a logical pool
|
||||
win = _open_createpool(app, hostwin)
|
||||
win.combo_select("Type:", "logical:")
|
||||
newname = "a-lvm-pool"
|
||||
name.set_text("a-lvm-pool")
|
||||
|
||||
win.combo_check_default("Volgroup", "testvg1")
|
||||
win.combo_select("Volgroup", "testvg2")
|
||||
finish.click()
|
||||
hostwin.find(newname, "table cell")
|
||||
|
||||
# Test a scsi pool
|
||||
win = _open_createpool(app, hostwin)
|
||||
win.combo_select("Type:", "scsi:")
|
||||
newname = "a-scsi-pool"
|
||||
name.set_text("a-scsi-pool")
|
||||
win.combo_select("Source Adapter:", "host2")
|
||||
finish.click()
|
||||
hostwin.find(newname, "table cell")
|
||||
|
||||
# Test a ceph pool
|
||||
win = _open_createpool(app, hostwin)
|
||||
newname = "a-ceph-pool"
|
||||
name.set_text("a-ceph-pool")
|
||||
win.combo_select("Type:", "rbd:")
|
||||
win.find_fuzzy("Host Name:", "text").set_text("example.com:1234")
|
||||
win.find_fuzzy("pool-source-name-text", "text").typeText("frob")
|
||||
finish.click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
hostwin.find(newname, "table cell")
|
||||
|
||||
# Ensure host window closes fine
|
||||
hostwin.click()
|
||||
hostwin.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: not hostwin.showing)
|
||||
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
|
||||
def testCreatePools(self):
|
||||
hostwin = self.app.open_host_window("Storage")
|
||||
win = self._open_create_win(hostwin)
|
||||
finish = win.find("Finish", "push button")
|
||||
name = win.find("Name:", "text")
|
||||
def testCreatePoolXMLEditor(app):
|
||||
app.open(xmleditor_enabled=True)
|
||||
hostwin = app.manager_open_host("Storage")
|
||||
win = _open_createpool(app, hostwin)
|
||||
finish = win.find("Finish", "push button")
|
||||
name = win.find("Name:", "text")
|
||||
|
||||
def _browse_local_path(winlabel, usepath):
|
||||
chooser = self.app.root.find(winlabel, "file chooser")
|
||||
# Enter the filename and select it
|
||||
chooser.find(usepath, "table cell").click()
|
||||
obutton = chooser.find("Open", "push button")
|
||||
lib.utils.check(lambda: obutton.sensitive)
|
||||
obutton.click()
|
||||
lib.utils.check(lambda: not chooser.showing)
|
||||
lib.utils.check(lambda: win.active)
|
||||
# Create a new obj with XML edited name, verify it worked
|
||||
tmpname = "objtmpname"
|
||||
newname = "froofroo"
|
||||
name.set_text(tmpname)
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
newtext = xmleditor.text.replace(">%s<" % tmpname, ">%s<" % newname)
|
||||
xmleditor.set_text(newtext)
|
||||
finish.click()
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
cell = hostwin.find(newname, "table cell")
|
||||
cell.click()
|
||||
|
||||
# Create a simple default dir pool
|
||||
lib.utils.check(lambda: name.text == "pool")
|
||||
newname = "a-test-new-pool"
|
||||
name.set_text(newname)
|
||||
finish.click()
|
||||
|
||||
# Select the new object in the host window, then do
|
||||
# stop->start->stop->delete, for lifecycle testing
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
cell = hostwin.find(newname, "table cell")
|
||||
delete = hostwin.find("pool-delete", "push button")
|
||||
start = hostwin.find("pool-start", "push button")
|
||||
stop = hostwin.find("pool-stop", "push button")
|
||||
|
||||
cell.click()
|
||||
stop.click()
|
||||
lib.utils.check(lambda: start.sensitive)
|
||||
start.click()
|
||||
lib.utils.check(lambda: stop.sensitive)
|
||||
stop.click()
|
||||
lib.utils.check(lambda: delete.sensitive)
|
||||
|
||||
# Delete it, clicking 'No' first
|
||||
delete.click()
|
||||
self.app.click_alert_button("permanently delete the pool", "No")
|
||||
lib.utils.check(lambda: not cell.dead)
|
||||
delete.click()
|
||||
self.app.click_alert_button("permanently delete the pool", "Yes")
|
||||
# Ensure it's gone
|
||||
lib.utils.check(lambda: cell.dead)
|
||||
|
||||
# Test a disk pool
|
||||
win = self._open_create_win(hostwin)
|
||||
win.combo_select("Type:", "disk:")
|
||||
newname = "a-disk-pool"
|
||||
name.set_text("a-disk-pool")
|
||||
win.find("source-browse").click()
|
||||
_browse_local_path("Choose source path", "console")
|
||||
finish.click()
|
||||
hostwin.find(newname, "table cell")
|
||||
|
||||
# Test a iscsi pool
|
||||
win = self._open_create_win(hostwin)
|
||||
win.combo_select("Type:", "iscsi:")
|
||||
newname = "a-iscsi-pool"
|
||||
name.set_text("a-iscsi-pool")
|
||||
win.find("target-browse").click()
|
||||
_browse_local_path("Choose target directory", "by-path")
|
||||
finish.click()
|
||||
# Catch example error
|
||||
self.app.click_alert_button("source host name", "Close")
|
||||
win.find("Host Name:", "text").set_text("example.com")
|
||||
win.find("pool-source-path-text").set_text("foo-iqn")
|
||||
win.find_fuzzy("Initiator IQN:", "check").click()
|
||||
win.find("iqn-text", "text").set_text("initiator-foo")
|
||||
finish.click()
|
||||
hostwin.find(newname, "table cell")
|
||||
|
||||
# Test a logical pool
|
||||
win = self._open_create_win(hostwin)
|
||||
win.combo_select("Type:", "logical:")
|
||||
newname = "a-lvm-pool"
|
||||
name.set_text("a-lvm-pool")
|
||||
|
||||
win.combo_check_default("Volgroup", "testvg1")
|
||||
win.combo_select("Volgroup", "testvg2")
|
||||
finish.click()
|
||||
hostwin.find(newname, "table cell")
|
||||
|
||||
# Test a scsi pool
|
||||
win = self._open_create_win(hostwin)
|
||||
win.combo_select("Type:", "scsi:")
|
||||
newname = "a-scsi-pool"
|
||||
name.set_text("a-scsi-pool")
|
||||
win.combo_select("Source Adapter:", "host2")
|
||||
finish.click()
|
||||
hostwin.find(newname, "table cell")
|
||||
|
||||
# Test a ceph pool
|
||||
win = self._open_create_win(hostwin)
|
||||
newname = "a-ceph-pool"
|
||||
name.set_text("a-ceph-pool")
|
||||
win.combo_select("Type:", "rbd:")
|
||||
win.find_fuzzy("Host Name:", "text").set_text("example.com:1234")
|
||||
win.find_fuzzy("pool-source-name-text", "text").typeText("frob")
|
||||
finish.click()
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
hostwin.find(newname, "table cell")
|
||||
|
||||
# Ensure host window closes fine
|
||||
hostwin.click()
|
||||
hostwin.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: not hostwin.showing)
|
||||
|
||||
|
||||
def testCreatePoolXMLEditor(self):
|
||||
self.app.open(xmleditor_enabled=True)
|
||||
hostwin = self.app.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.set_text(tmpname)
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
newtext = xmleditor.text.replace(">%s<" % tmpname, ">%s<" % newname)
|
||||
xmleditor.set_text(newtext)
|
||||
finish.click()
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
cell = hostwin.find(newname, "table cell")
|
||||
cell.click()
|
||||
|
||||
# Do standard xmleditor tests
|
||||
win = self._open_create_win(hostwin)
|
||||
lib.utils.test_xmleditor_interactions(self.app, win, finish)
|
||||
win.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.visible)
|
||||
# Do standard xmleditor tests
|
||||
win = _open_createpool(app, hostwin)
|
||||
lib.utils.test_xmleditor_interactions(app, win, finish)
|
||||
win.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.visible)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,158 +4,154 @@
|
|||
from . import lib
|
||||
|
||||
|
||||
class CreateVol(lib.testcase.UITestCase):
|
||||
#####################################
|
||||
# UI tests for the createvol wizard #
|
||||
#####################################
|
||||
|
||||
def _open_createvol(app, hostwin):
|
||||
hostwin.find("vol-new", "push button").click()
|
||||
win = app.find_window("Add a Storage Volume")
|
||||
lib.utils.check(lambda: win.active)
|
||||
return win
|
||||
|
||||
|
||||
def testCreateVolDefault(app):
|
||||
"""
|
||||
UI tests for the createvol wizard
|
||||
Create default volume, clean it up
|
||||
"""
|
||||
hostwin = app.manager_open_host("Storage")
|
||||
poolcell = hostwin.find("default-pool", "table cell")
|
||||
poolcell.click()
|
||||
vollist = hostwin.find("vol-list", "table")
|
||||
win = _open_createvol(app, hostwin)
|
||||
finish = win.find("Finish", "push button")
|
||||
name = win.find("Name:", "text")
|
||||
|
||||
def _open_create_win(self, hostwin):
|
||||
hostwin.find("vol-new", "push button").click()
|
||||
win = self.app.root.find(
|
||||
"Add a Storage Volume", "frame")
|
||||
lib.utils.check(lambda: win.active)
|
||||
return win
|
||||
# Create a default qcow2 volume
|
||||
lib.utils.check(lambda: name.text == "vol")
|
||||
newname = "a-newvol"
|
||||
name.set_text(newname)
|
||||
win.find("Max Capacity:", "spin button").set_text("10.5")
|
||||
finish.click()
|
||||
|
||||
# Delete it, clicking 'No' first
|
||||
volcell = vollist.find(newname + ".qcow2")
|
||||
volcell.click()
|
||||
hostwin.find("vol-refresh", "push button").click()
|
||||
hostwin.find("vol-delete", "push button").click()
|
||||
app.click_alert_button("permanently delete the volume", "No")
|
||||
volcell = vollist.find(newname + ".qcow2")
|
||||
hostwin.find("vol-delete", "push button").click()
|
||||
app.click_alert_button("permanently delete the volume", "Yes")
|
||||
lib.utils.check(lambda: volcell.dead)
|
||||
|
||||
# Ensure host window closes fine
|
||||
hostwin.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: not hostwin.showing and
|
||||
not hostwin.active)
|
||||
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
def testCreateVolMisc(app):
|
||||
"""
|
||||
Cover all createvol options
|
||||
"""
|
||||
hostwin = app.manager_open_host("Storage")
|
||||
poolcell = hostwin.find("default-pool", "table cell")
|
||||
poolcell.click()
|
||||
win = _open_createvol(app, hostwin)
|
||||
name = win.find("Name:", "text")
|
||||
finish = win.find("Finish", "push button")
|
||||
vollist = hostwin.find("vol-list", "table")
|
||||
|
||||
def testCreateVolDefault(self):
|
||||
"""
|
||||
Create default volume, clean it up
|
||||
"""
|
||||
hostwin = self.app.open_host_window("Storage")
|
||||
poolcell = hostwin.find("default-pool", "table cell")
|
||||
poolcell.click()
|
||||
vollist = hostwin.find("vol-list", "table")
|
||||
win = self._open_create_win(hostwin)
|
||||
finish = win.find("Finish", "push button")
|
||||
name = win.find("Name:", "text")
|
||||
# Create a qcow2 with backing file
|
||||
newname = "aaa-qcow2-backing.qcow2"
|
||||
name.set_text(newname)
|
||||
win.combo_select("Format:", "qcow2")
|
||||
win.find("Backing store").click_expander()
|
||||
win.find("Browse...").click()
|
||||
browsewin = app.root.find("vmm-storage-browser")
|
||||
# Test cancel button
|
||||
browsewin.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not browsewin.active)
|
||||
win.find("Browse...").click()
|
||||
browsewin = app.root.find("vmm-storage-browser")
|
||||
# Test browse local opening
|
||||
browsewin.find("Browse Local", "push button").click()
|
||||
chooser = app.root.find(
|
||||
"Locate existing storage", "file chooser")
|
||||
chooser.keyCombo("<alt>F4")
|
||||
app.select_storagebrowser_volume(
|
||||
"default-pool", "bochs-vol", doubleclick=True)
|
||||
backingstore = win.find("backing-store")
|
||||
lib.utils.check(lambda: "bochs-vol" in backingstore.text)
|
||||
finish.click()
|
||||
vollist.find(newname)
|
||||
|
||||
# Create a default qcow2 volume
|
||||
lib.utils.check(lambda: name.text == "vol")
|
||||
newname = "a-newvol"
|
||||
name.set_text(newname)
|
||||
win.find("Max Capacity:", "spin button").set_text("10.5")
|
||||
finish.click()
|
||||
# Create a raw volume with some size tweaking
|
||||
win = _open_createvol(app, hostwin)
|
||||
# Using previous name so we collide
|
||||
name.set_text(newname)
|
||||
win.combo_select("Format:", "raw")
|
||||
cap = win.find("Max Capacity:", "spin button")
|
||||
alloc = win.find("Allocation:", "spin button")
|
||||
alloc.set_text("50.0")
|
||||
alloc.click()
|
||||
app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: cap.text == "50.0")
|
||||
cap.set_text("1.0")
|
||||
cap.click()
|
||||
app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: alloc.text == "1.0")
|
||||
alloc.set_text("0.5")
|
||||
alloc.click()
|
||||
app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: cap.text == "1.0")
|
||||
|
||||
# Delete it, clicking 'No' first
|
||||
volcell = vollist.find(newname + ".qcow2")
|
||||
volcell.click()
|
||||
hostwin.find("vol-refresh", "push button").click()
|
||||
hostwin.find("vol-delete", "push button").click()
|
||||
self.app.click_alert_button("permanently delete the volume", "No")
|
||||
volcell = vollist.find(newname + ".qcow2")
|
||||
hostwin.find("vol-delete", "push button").click()
|
||||
self.app.click_alert_button("permanently delete the volume", "Yes")
|
||||
lib.utils.check(lambda: volcell.dead)
|
||||
finish.click()
|
||||
app.click_alert_button("Error validating volume", "Close")
|
||||
newname = "a-newvol.raw"
|
||||
name.set_text(newname)
|
||||
finish.click()
|
||||
vollist.find(newname)
|
||||
|
||||
# Ensure host window closes fine
|
||||
hostwin.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: not hostwin.showing and
|
||||
not hostwin.active)
|
||||
|
||||
def testCreateVolMisc(self):
|
||||
"""
|
||||
Cover all createvol options
|
||||
"""
|
||||
hostwin = self.app.open_host_window("Storage")
|
||||
poolcell = hostwin.find("default-pool", "table cell")
|
||||
poolcell.click()
|
||||
win = self._open_create_win(hostwin)
|
||||
name = win.find("Name:", "text")
|
||||
finish = win.find("Finish", "push button")
|
||||
vollist = hostwin.find("vol-list", "table")
|
||||
|
||||
# Create a qcow2 with backing file
|
||||
newname = "aaa-qcow2-backing.qcow2"
|
||||
name.set_text(newname)
|
||||
win.combo_select("Format:", "qcow2")
|
||||
win.find("Backing store").click_expander()
|
||||
win.find("Browse...").click()
|
||||
browsewin = self.app.root.find("vmm-storage-browser")
|
||||
# Test cancel button
|
||||
browsewin.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not browsewin.active)
|
||||
win.find("Browse...").click()
|
||||
browsewin = self.app.root.find("vmm-storage-browser")
|
||||
# Test browse local opening
|
||||
browsewin.find("Browse Local", "push button").click()
|
||||
chooser = self.app.root.find(
|
||||
"Locate existing storage", "file chooser")
|
||||
chooser.keyCombo("<alt>F4")
|
||||
self.app.select_storagebrowser_volume(
|
||||
"default-pool", "bochs-vol", doubleclick=True)
|
||||
backingstore = win.find("backing-store")
|
||||
lib.utils.check(lambda: "bochs-vol" in backingstore.text)
|
||||
finish.click()
|
||||
vollist.find(newname)
|
||||
|
||||
# Create a raw volume with some size tweaking
|
||||
win = self._open_create_win(hostwin)
|
||||
# Using previous name so we collide
|
||||
name.set_text(newname)
|
||||
win.combo_select("Format:", "raw")
|
||||
cap = win.find("Max Capacity:", "spin button")
|
||||
alloc = win.find("Allocation:", "spin button")
|
||||
alloc.set_text("50.0")
|
||||
alloc.click()
|
||||
self.app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: cap.text == "50.0")
|
||||
cap.set_text("1.0")
|
||||
cap.click()
|
||||
self.app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: alloc.text == "1.0")
|
||||
alloc.set_text("0.5")
|
||||
alloc.click()
|
||||
self.app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: cap.text == "1.0")
|
||||
|
||||
finish.click()
|
||||
self.app.click_alert_button("Error validating volume", "Close")
|
||||
newname = "a-newvol.raw"
|
||||
name.set_text(newname)
|
||||
finish.click()
|
||||
vollist.find(newname)
|
||||
|
||||
# Create LVM backing store
|
||||
hostwin.find("disk-pool", "table cell").click()
|
||||
win = self._open_create_win(hostwin)
|
||||
newname = "aaa-lvm"
|
||||
name.set_text(newname)
|
||||
win.find("Backing store").click_expander()
|
||||
win.find("Browse...").click()
|
||||
self.app.select_storagebrowser_volume("disk-pool", "diskvol7")
|
||||
finish.click()
|
||||
vollist.find(newname)
|
||||
# Create LVM backing store
|
||||
hostwin.find("disk-pool", "table cell").click()
|
||||
win = _open_createvol(app, hostwin)
|
||||
newname = "aaa-lvm"
|
||||
name.set_text(newname)
|
||||
win.find("Backing store").click_expander()
|
||||
win.find("Browse...").click()
|
||||
app.select_storagebrowser_volume("disk-pool", "diskvol7")
|
||||
finish.click()
|
||||
vollist.find(newname)
|
||||
|
||||
|
||||
def testCreateVolXMLEditor(self):
|
||||
self.app.open(xmleditor_enabled=True)
|
||||
hostwin = self.app.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.set_text(tmpname)
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
newtext = xmleditor.text.replace(
|
||||
">%s.qcow2<" % tmpname, ">%s<" % newname)
|
||||
xmleditor.set_text(newtext)
|
||||
finish.click()
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
vollist.find(newname)
|
||||
def testCreateVolXMLEditor(app):
|
||||
app.open(xmleditor_enabled=True)
|
||||
hostwin = app.manager_open_host("Storage")
|
||||
poolcell = hostwin.find("default-pool", "table cell")
|
||||
poolcell.click()
|
||||
win = _open_createvol(app, hostwin)
|
||||
finish = win.find("Finish", "push button")
|
||||
name = win.find("Name:", "text")
|
||||
vollist = hostwin.find("vol-list", "table")
|
||||
|
||||
# Do standard xmleditor tests
|
||||
win = self._open_create_win(hostwin)
|
||||
lib.utils.test_xmleditor_interactions(self.app, win, finish)
|
||||
win.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.visible)
|
||||
# Create a new obj with XML edited name, verify it worked
|
||||
tmpname = "objtmpname"
|
||||
newname = "aafroofroo"
|
||||
name.set_text(tmpname)
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
newtext = xmleditor.text.replace(
|
||||
">%s.qcow2<" % tmpname, ">%s<" % newname)
|
||||
xmleditor.set_text(newtext)
|
||||
finish.click()
|
||||
lib.utils.check(lambda: hostwin.active)
|
||||
vollist.find(newname)
|
||||
|
||||
# Do standard xmleditor tests
|
||||
win = _open_createvol(app, hostwin)
|
||||
lib.utils.test_xmleditor_interactions(app, win, finish)
|
||||
win.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.visible)
|
||||
|
|
|
@ -23,7 +23,7 @@ class _DeleteRow:
|
|||
|
||||
|
||||
def _create_testdriver_path(fn):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
def wrapper(app, *args, **kwargs):
|
||||
# This special path is hardcoded in test-many-devices
|
||||
tmppath = "/tmp/virt-manager-uitests/tmp1"
|
||||
tmpdir = os.path.dirname(tmppath)
|
||||
|
@ -32,7 +32,7 @@ def _create_testdriver_path(fn):
|
|||
os.mkdir(tmpdir)
|
||||
open(tmppath, "w").write("foo")
|
||||
os.chmod(tmppath, 0o444)
|
||||
return fn(self, tmppath, *args, **kwargs)
|
||||
return fn(app, tmppath, *args, **kwargs)
|
||||
finally:
|
||||
if os.path.exists(tmpdir):
|
||||
os.chmod(tmpdir, 0o777)
|
||||
|
@ -40,267 +40,276 @@ def _create_testdriver_path(fn):
|
|||
return wrapper
|
||||
|
||||
|
||||
class Delete(lib.testcase.UITestCase):
|
||||
"""
|
||||
UI tests for virt-manager's VM delete window
|
||||
"""
|
||||
def _open_storage_browser(self):
|
||||
self.app.root.find("New", "push button").click()
|
||||
newvm = self.app.root.find("New VM", "frame")
|
||||
newvm.find_fuzzy("Local install media", "radio").click()
|
||||
newvm.find_fuzzy("Forward", "button").click()
|
||||
newvm.find_fuzzy("install-iso-browse", "button").click()
|
||||
return self.app.root.find("vmm-storage-browser")
|
||||
def _open_storage_browser(app):
|
||||
app.root.find("New", "push button").click()
|
||||
newvm = app.find_window("New VM")
|
||||
newvm.find_fuzzy("Local install media", "radio").click()
|
||||
newvm.find_fuzzy("Forward", "button").click()
|
||||
newvm.find_fuzzy("install-iso-browse", "button").click()
|
||||
return app.root.find("vmm-storage-browser")
|
||||
|
||||
def _open_delete(self, vmname):
|
||||
manager = self.app.topwin
|
||||
cell = manager.find(vmname, "table cell")
|
||||
cell.click()
|
||||
cell.click(button=3)
|
||||
menu = self.app.root.find("vm-action-menu")
|
||||
menu.find("Delete", "menu item").click()
|
||||
|
||||
return self.app.root.find_fuzzy("Delete", "frame")
|
||||
def _open_delete(app, vmname):
|
||||
app.manager_vm_action(vmname, delete=True)
|
||||
return app.find_window("Delete")
|
||||
|
||||
def _finish(self, delete, paths, expect_fail=False, click_no=False):
|
||||
delete.find_fuzzy("Delete", "button").click()
|
||||
if paths:
|
||||
alert = self.app.root.find("vmm dialog", "alert")
|
||||
alert.find_fuzzy("Are you sure")
|
||||
for path in paths:
|
||||
alert.find_fuzzy(path)
|
||||
if click_no:
|
||||
alert.find("No", "push button").click()
|
||||
return
|
||||
alert.find("Yes", "push button").click()
|
||||
if not expect_fail:
|
||||
lib.utils.check(lambda: not delete.showing)
|
||||
|
||||
def _get_all_rows(self, delete):
|
||||
def _finish(app, delete, paths, expect_fail=False, click_no=False):
|
||||
delete.find_fuzzy("Delete", "button").click()
|
||||
if paths:
|
||||
alert = app.root.find("vmm dialog", "alert")
|
||||
alert.find_fuzzy("Are you sure")
|
||||
for path in paths:
|
||||
alert.find_fuzzy(path)
|
||||
if click_no:
|
||||
alert.find("No", "push button").click()
|
||||
return
|
||||
alert.find("Yes", "push button").click()
|
||||
if not expect_fail:
|
||||
lib.utils.check(lambda: not delete.showing)
|
||||
|
||||
|
||||
def _get_all_rows(delete):
|
||||
slist = delete.find("storage-list")
|
||||
def pred(node):
|
||||
return node.roleName == "table cell"
|
||||
cells = slist.findChildren(pred, isLambda=True)
|
||||
|
||||
idx = 0
|
||||
rows = []
|
||||
while idx < len(cells):
|
||||
rows.append(_DeleteRow(*cells[idx:idx + 4]))
|
||||
idx += 4
|
||||
return rows
|
||||
|
||||
|
||||
################################################
|
||||
# UI tests for virt-manager's VM delete window #
|
||||
################################################
|
||||
|
||||
def _testDeleteManyDevices(app,
|
||||
nondefault_path=None, delete_nondefault=False,
|
||||
skip_finish=False):
|
||||
delete = _open_delete(app, "test-many-devices")
|
||||
|
||||
rows = _get_all_rows(delete)
|
||||
selected_rows = [r.path for r in rows if r.default]
|
||||
undeletable_rows = [r.path for r in rows if r.undeletable]
|
||||
notdefault_rows = [r.path for r in rows if r.notdefault]
|
||||
|
||||
defpath = "/dev/default-pool/overlay.img"
|
||||
nondefault_path2 = "/dev/default-pool/sharevol.img"
|
||||
|
||||
assert selected_rows == [defpath]
|
||||
if nondefault_path:
|
||||
assert nondefault_path in notdefault_rows
|
||||
assert nondefault_path2 in notdefault_rows
|
||||
assert "/dev/fda" in undeletable_rows
|
||||
|
||||
if delete_nondefault:
|
||||
# Click the selector for the nondefault path
|
||||
found = [r for r in rows if r.path == nondefault_path]
|
||||
assert len(found) == 1
|
||||
slist = delete.find("storage-list")
|
||||
def pred(node):
|
||||
return node.roleName == "table cell"
|
||||
cells = slist.findChildren(pred, isLambda=True)
|
||||
slist.click()
|
||||
chkcell = found[0].chkcell
|
||||
chkcell.bring_on_screen()
|
||||
chkcell.click()
|
||||
chkcell.click()
|
||||
chkcell.click()
|
||||
lib.utils.check(lambda: chkcell.checked)
|
||||
|
||||
idx = 0
|
||||
rows = []
|
||||
while idx < len(cells):
|
||||
rows.append(_DeleteRow(*cells[idx:idx + 4]))
|
||||
idx += 4
|
||||
return rows
|
||||
paths = []
|
||||
if defpath:
|
||||
paths.append(defpath)
|
||||
if delete_nondefault:
|
||||
paths.append(nondefault_path)
|
||||
if skip_finish:
|
||||
return paths
|
||||
_finish(app, delete, paths)
|
||||
|
||||
# Confirm
|
||||
browser = _open_storage_browser(app)
|
||||
browser.find_fuzzy("default-pool", "table cell").click()
|
||||
browser.find("vol-refresh", "push button").click()
|
||||
lib.utils.check(lambda: "overlay.img" not in browser.fmt_nodes())
|
||||
browser.find("sharevol.img", "table cell")
|
||||
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
@_create_testdriver_path
|
||||
def testDeleteManyDevices(app, tmppath):
|
||||
"""
|
||||
Hit a specific case of a path not selected by default
|
||||
because the permissions are readonly
|
||||
"""
|
||||
_testDeleteManyDevices(app, nondefault_path=tmppath)
|
||||
|
||||
def _testDeleteManyDevices(self,
|
||||
nondefault_path=None, delete_nondefault=False,
|
||||
skip_finish=False):
|
||||
delete = self._open_delete("test-many-devices")
|
||||
|
||||
rows = self._get_all_rows(delete)
|
||||
selected_rows = [r.path for r in rows if r.default]
|
||||
undeletable_rows = [r.path for r in rows if r.undeletable]
|
||||
notdefault_rows = [r.path for r in rows if r.notdefault]
|
||||
@_create_testdriver_path
|
||||
def testDeleteNondefaultOverride(app, tmppath):
|
||||
"""
|
||||
Path not selected by default, but we select it,
|
||||
which will cause it to be manually unlinked
|
||||
"""
|
||||
_testDeleteManyDevices(app,
|
||||
nondefault_path=tmppath,
|
||||
delete_nondefault=True)
|
||||
assert not os.path.exists(tmppath)
|
||||
|
||||
defpath = "/dev/default-pool/overlay.img"
|
||||
nondefault_path2 = "/dev/default-pool/sharevol.img"
|
||||
|
||||
assert selected_rows == [defpath]
|
||||
if nondefault_path:
|
||||
assert nondefault_path in notdefault_rows
|
||||
assert nondefault_path2 in notdefault_rows
|
||||
assert "/dev/fda" in undeletable_rows
|
||||
@_create_testdriver_path
|
||||
def testDeleteFailure(app, tmppath):
|
||||
"""
|
||||
After launching the wizard we change permissions to make
|
||||
file deletion fail
|
||||
"""
|
||||
paths = _testDeleteManyDevices(app,
|
||||
nondefault_path=tmppath,
|
||||
delete_nondefault=True,
|
||||
skip_finish=True)
|
||||
os.chmod(os.path.dirname(tmppath), 0o555)
|
||||
delete = app.find_window("Delete")
|
||||
_finish(app, delete, paths, expect_fail=True, click_no=True)
|
||||
lib.utils.check(lambda: delete.active)
|
||||
_finish(app, delete, paths, expect_fail=True)
|
||||
assert os.path.exists(tmppath)
|
||||
app.click_alert_button("Errors encountered", "Close")
|
||||
|
||||
if delete_nondefault:
|
||||
# Click the selector for the nondefault path
|
||||
found = [r for r in rows if r.path == nondefault_path]
|
||||
assert len(found) == 1
|
||||
slist = delete.find("storage-list")
|
||||
slist.click()
|
||||
chkcell = found[0].chkcell
|
||||
chkcell.bring_on_screen()
|
||||
chkcell.click()
|
||||
chkcell.click()
|
||||
chkcell.click()
|
||||
lib.utils.check(lambda: chkcell.checked)
|
||||
# Ensure disconnecting will close the dialog
|
||||
manager = app.topwin
|
||||
manager.window_maximize()
|
||||
win = _open_delete(app, "test-clone")
|
||||
manager.click_title()
|
||||
app.manager_conn_disconnect("test testdriver.xml")
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
paths = []
|
||||
if defpath:
|
||||
paths.append(defpath)
|
||||
if delete_nondefault:
|
||||
paths.append(nondefault_path)
|
||||
if skip_finish:
|
||||
return paths
|
||||
self._finish(delete, paths)
|
||||
|
||||
# Confirm
|
||||
browser = self._open_storage_browser()
|
||||
browser.find_fuzzy("default-pool", "table cell").click()
|
||||
browser.find("vol-refresh", "push button").click()
|
||||
lib.utils.check(lambda: "overlay.img" not in browser.fmt_nodes())
|
||||
browser.find("sharevol.img", "table cell")
|
||||
def testDeleteRemoteManyDevices(app):
|
||||
"""
|
||||
Test with a remote VM to hit a certain code path
|
||||
"""
|
||||
app.uri = tests.utils.URIs.kvm_remote
|
||||
_testDeleteManyDevices(app)
|
||||
|
||||
@_create_testdriver_path
|
||||
def testDeleteManyDevices(self, tmppath):
|
||||
"""
|
||||
Hit a specific case of a path not selected by default
|
||||
because the permissions are readonly
|
||||
"""
|
||||
self._testDeleteManyDevices(nondefault_path=tmppath)
|
||||
|
||||
@_create_testdriver_path
|
||||
def testDeleteNondefaultOverride(self, tmppath):
|
||||
"""
|
||||
Path not selected by default, but we select it,
|
||||
which will cause it to be manually unlinked
|
||||
"""
|
||||
self._testDeleteManyDevices(
|
||||
nondefault_path=tmppath,
|
||||
delete_nondefault=True)
|
||||
assert not os.path.exists(tmppath)
|
||||
def testDeleteSkipStorage(app):
|
||||
"""
|
||||
Test VM delete with all storage skipped
|
||||
"""
|
||||
delete = _open_delete(app, "test-many-devices")
|
||||
chk = delete.find("Delete associated", "check box")
|
||||
slist = delete.find("storage-list")
|
||||
|
||||
@_create_testdriver_path
|
||||
def testDeleteFailure(self, tmppath):
|
||||
"""
|
||||
After launching the wizard we change permissions to make
|
||||
file deletion fail
|
||||
"""
|
||||
paths = self._testDeleteManyDevices(
|
||||
nondefault_path=tmppath,
|
||||
delete_nondefault=True,
|
||||
skip_finish=True)
|
||||
os.chmod(os.path.dirname(tmppath), 0o555)
|
||||
delete = self.app.root.find_fuzzy("Delete", "frame")
|
||||
self._finish(delete, paths, expect_fail=True, click_no=True)
|
||||
lib.utils.check(lambda: delete.active)
|
||||
self._finish(delete, paths, expect_fail=True)
|
||||
assert os.path.exists(tmppath)
|
||||
self.app.click_alert_button("Errors encountered", "Close")
|
||||
lib.utils.check(lambda: chk.checked)
|
||||
chk.click()
|
||||
lib.utils.check(lambda: not chk.checked)
|
||||
lib.utils.check(lambda: not slist.showing)
|
||||
|
||||
def testDeleteRemoteManyDevices(self):
|
||||
"""
|
||||
Test with a remote VM to hit a certain code path
|
||||
"""
|
||||
self.app.uri = tests.utils.URIs.kvm_remote
|
||||
self._testDeleteManyDevices()
|
||||
_finish(app, delete, None)
|
||||
|
||||
def testDeleteSkipStorage(self):
|
||||
"""
|
||||
Test VM delete with all storage skipped
|
||||
"""
|
||||
delete = self._open_delete("test-many-devices")
|
||||
chk = delete.find("Delete associated", "check box")
|
||||
slist = delete.find("storage-list")
|
||||
# Confirm nothing was deleted compare to the default selections
|
||||
browser = _open_storage_browser(app)
|
||||
browser.find_fuzzy("default-pool", "table cell").click()
|
||||
browser.find("vol-refresh", "push button").click()
|
||||
app.sleep(.5)
|
||||
browser.find("overlay.img", "table cell")
|
||||
browser.find("sharevol.img", "table cell")
|
||||
|
||||
lib.utils.check(lambda: chk.checked)
|
||||
chk.click()
|
||||
lib.utils.check(lambda: not chk.checked)
|
||||
lib.utils.check(lambda: not slist.showing)
|
||||
|
||||
self._finish(delete, None)
|
||||
def testDeleteDeviceNoStorage(app):
|
||||
"""
|
||||
Verify successful device remove with storage doesn't
|
||||
touch host storage
|
||||
"""
|
||||
details = app.manager_open_details("test-many-devices",
|
||||
shutdown=True)
|
||||
|
||||
# Confirm nothing was deleted compare to the default selections
|
||||
browser = self._open_storage_browser()
|
||||
browser.find_fuzzy("default-pool", "table cell").click()
|
||||
browser.find("vol-refresh", "push button").click()
|
||||
self.app.sleep(.5)
|
||||
browser.find("overlay.img", "table cell")
|
||||
browser.find("sharevol.img", "table cell")
|
||||
hwlist = details.find("hw-list")
|
||||
hwlist.click()
|
||||
c = hwlist.find("USB Disk 1")
|
||||
c.bring_on_screen()
|
||||
c.click()
|
||||
tab = details.find("disk-tab")
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
details.find("config-remove").click()
|
||||
|
||||
def testDeleteDeviceNoStorage(self):
|
||||
"""
|
||||
Verify successful device remove with storage doesn't
|
||||
touch host storage
|
||||
"""
|
||||
details = self.app.open_details_window("test-many-devices",
|
||||
shutdown=True)
|
||||
delete = app.find_window("Remove Disk")
|
||||
chk = delete.find("Delete associated", "check box")
|
||||
lib.utils.check(lambda: not chk.checked)
|
||||
_finish(app, delete, [])
|
||||
details.click()
|
||||
details.keyCombo("<alt>F4")
|
||||
|
||||
hwlist = details.find("hw-list")
|
||||
hwlist.click()
|
||||
c = hwlist.find("USB Disk 1")
|
||||
c.bring_on_screen()
|
||||
c.click()
|
||||
tab = details.find("disk-tab")
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
details.find("config-remove").click()
|
||||
browser = _open_storage_browser(app)
|
||||
browser.find_fuzzy("default-pool", "table cell").click()
|
||||
browser.find("vol-refresh", "push button").click()
|
||||
app.sleep(.5)
|
||||
browser.find("overlay.img", "table cell")
|
||||
|
||||
delete = self.app.root.find_fuzzy("Remove Disk", "frame")
|
||||
chk = delete.find("Delete associated", "check box")
|
||||
lib.utils.check(lambda: not chk.checked)
|
||||
self._finish(delete, [])
|
||||
details.click()
|
||||
details.keyCombo("<alt>F4")
|
||||
|
||||
browser = self._open_storage_browser()
|
||||
browser.find_fuzzy("default-pool", "table cell").click()
|
||||
browser.find("vol-refresh", "push button").click()
|
||||
self.app.sleep(.5)
|
||||
browser.find("overlay.img", "table cell")
|
||||
def testDeleteDeviceWithStorage(app):
|
||||
"""
|
||||
Verify successful device remove deletes storage
|
||||
"""
|
||||
details = app.manager_open_details("test-many-devices",
|
||||
shutdown=True)
|
||||
|
||||
def testDeleteDeviceWithStorage(self):
|
||||
"""
|
||||
Verify successful device remove deletes storage
|
||||
"""
|
||||
details = self.app.open_details_window("test-many-devices",
|
||||
shutdown=True)
|
||||
hwlist = details.find("hw-list")
|
||||
hwlist.click()
|
||||
c = hwlist.find("USB Disk 1")
|
||||
c.bring_on_screen()
|
||||
c.click()
|
||||
tab = details.find("disk-tab")
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
details.find("config-remove").click()
|
||||
|
||||
hwlist = details.find("hw-list")
|
||||
hwlist.click()
|
||||
c = hwlist.find("USB Disk 1")
|
||||
c.bring_on_screen()
|
||||
c.click()
|
||||
tab = details.find("disk-tab")
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
details.find("config-remove").click()
|
||||
delete = app.find_window("Remove Disk")
|
||||
chk = delete.find("Delete associated", "check box")
|
||||
lib.utils.check(lambda: not chk.checked)
|
||||
chk.click()
|
||||
lib.utils.check(lambda: chk.checked)
|
||||
path = "/dev/default-pool/overlay.img"
|
||||
delete.find_fuzzy(path)
|
||||
_finish(app, delete, [path])
|
||||
details.click()
|
||||
details.keyCombo("<alt>F4")
|
||||
|
||||
delete = self.app.root.find_fuzzy("Remove Disk", "frame")
|
||||
chk = delete.find("Delete associated", "check box")
|
||||
lib.utils.check(lambda: not chk.checked)
|
||||
chk.click()
|
||||
lib.utils.check(lambda: chk.checked)
|
||||
path = "/dev/default-pool/overlay.img"
|
||||
delete.find_fuzzy(path)
|
||||
self._finish(delete, [path])
|
||||
details.click()
|
||||
details.keyCombo("<alt>F4")
|
||||
browser = _open_storage_browser(app)
|
||||
browser.find_fuzzy("default-pool", "table cell").click()
|
||||
browser.find("vol-refresh", "push button").click()
|
||||
lib.utils.check(lambda: "overlay.img" not in browser.fmt_nodes())
|
||||
|
||||
browser = self._open_storage_browser()
|
||||
browser.find_fuzzy("default-pool", "table cell").click()
|
||||
browser.find("vol-refresh", "push button").click()
|
||||
lib.utils.check(lambda: "overlay.img" not in browser.fmt_nodes())
|
||||
|
||||
def testDeleteDeviceFail(self):
|
||||
"""
|
||||
Verify failed device remove does not touch storage
|
||||
"""
|
||||
details = self.app.open_details_window("test-many-devices")
|
||||
def testDeleteDeviceFail(app):
|
||||
"""
|
||||
Verify failed device remove does not touch storage
|
||||
"""
|
||||
details = app.manager_open_details("test-many-devices")
|
||||
|
||||
hwlist = details.find("hw-list")
|
||||
hwlist.click()
|
||||
c = hwlist.find("USB Disk 1")
|
||||
c.bring_on_screen()
|
||||
c.click()
|
||||
tab = details.find("disk-tab")
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
details.find("config-remove").click()
|
||||
hwlist = details.find("hw-list")
|
||||
hwlist.click()
|
||||
c = hwlist.find("USB Disk 1")
|
||||
c.bring_on_screen()
|
||||
c.click()
|
||||
tab = details.find("disk-tab")
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
details.find("config-remove").click()
|
||||
|
||||
delete = self.app.root.find_fuzzy("Remove Disk", "frame")
|
||||
chk = delete.find("Delete associated", "check box")
|
||||
lib.utils.check(lambda: not chk.checked)
|
||||
chk.click()
|
||||
lib.utils.check(lambda: chk.checked)
|
||||
path = "/dev/default-pool/overlay.img"
|
||||
delete.find_fuzzy(path)
|
||||
self._finish(delete, [path], expect_fail=True)
|
||||
self.app.click_alert_button("Storage will not be.*deleted", "OK")
|
||||
details.click()
|
||||
details.keyCombo("<alt>F4")
|
||||
delete = app.find_window("Remove Disk")
|
||||
chk = delete.find("Delete associated", "check box")
|
||||
lib.utils.check(lambda: not chk.checked)
|
||||
chk.click()
|
||||
lib.utils.check(lambda: chk.checked)
|
||||
path = "/dev/default-pool/overlay.img"
|
||||
delete.find_fuzzy(path)
|
||||
_finish(app, delete, [path], expect_fail=True)
|
||||
app.click_alert_button("Storage will not be.*deleted", "OK")
|
||||
details.click()
|
||||
details.keyCombo("<alt>F4")
|
||||
|
||||
# Verify file still exists
|
||||
browser = self._open_storage_browser()
|
||||
browser.find_fuzzy("default-pool", "table cell").click()
|
||||
browser.find("vol-refresh", "push button").click()
|
||||
self.app.sleep(.5)
|
||||
browser.find("overlay.img", "table cell")
|
||||
# Verify file still exists
|
||||
browser = _open_storage_browser(app)
|
||||
browser.find_fuzzy("default-pool", "table cell").click()
|
||||
browser.find("vol-refresh", "push button").click()
|
||||
app.sleep(.5)
|
||||
browser.find("overlay.img", "table cell")
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,182 +4,180 @@
|
|||
from . import lib
|
||||
|
||||
|
||||
class Host(lib.testcase.UITestCase):
|
||||
#################################################
|
||||
# UI tests for virt-manager's VM details window #
|
||||
#################################################
|
||||
|
||||
def testHostNetworkSmokeTest(app):
|
||||
"""
|
||||
UI tests for virt-manager's VM details window
|
||||
Verify that each virtual network displays, without error.
|
||||
"""
|
||||
win = app.manager_open_host("Virtual Networks")
|
||||
lst = win.find("net-list", "table")
|
||||
errlabel = win.find("net-error-label", "label")
|
||||
lib.utils.walkUIList(app, win, lst, lambda: errlabel.showing)
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
|
||||
def testHostNetworkSmokeTest(self):
|
||||
"""
|
||||
Verify that each virtual network displays, without error.
|
||||
"""
|
||||
win = self.app.open_host_window("Virtual Networks")
|
||||
lst = win.find("net-list", "table")
|
||||
errlabel = win.find("net-error-label", "label")
|
||||
lib.utils.walkUIList(self.app, win, lst, lambda: errlabel.showing)
|
||||
|
||||
# Select XML editor, and reverse walk the list
|
||||
win.find("network-grid").find("XML", "page tab").click()
|
||||
lib.utils.walkUIList(self.app, win, lst, lambda: errlabel.showing, reverse=True)
|
||||
|
||||
def testHostNetworkEdit(self):
|
||||
"""
|
||||
Test edits to net config
|
||||
"""
|
||||
self.app.open(xmleditor_enabled=True)
|
||||
win = self.app.open_host_window("Virtual Networks").find("network-grid")
|
||||
finish = win.find("Apply", "push button")
|
||||
|
||||
# Shut it off, 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()
|
||||
lib.utils.check(lambda: delete.sensitive)
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
origdev = "virbr0"
|
||||
newdev = "virbr77"
|
||||
xmleditor.set_text(xmleditor.text.replace(origdev, newdev))
|
||||
finish.click()
|
||||
win.find("Details", "page tab").click()
|
||||
netdev = win.find("net-device")
|
||||
lib.utils.check(lambda: netdev.text == newdev)
|
||||
|
||||
# Rename it
|
||||
win.find("default", "table cell").click()
|
||||
win.find("net-name").set_text("newsort-default")
|
||||
finish.click()
|
||||
|
||||
# Change autostart, trigger it by clicking away
|
||||
win.find("newsort-default", "table cell").click()
|
||||
win.find("net-autostart").click()
|
||||
win.find("netboot", "table cell").click()
|
||||
self.app.click_alert_button("There are unapplied changes", "Yes")
|
||||
|
||||
# Do standard xmleditor tests
|
||||
lib.utils.test_xmleditor_interactions(self.app, win, finish)
|
||||
# Select XML editor, and reverse walk the list
|
||||
win.find("network-grid").find("XML", "page tab").click()
|
||||
lib.utils.walkUIList(app, win, lst, lambda: errlabel.showing, reverse=True)
|
||||
|
||||
|
||||
def testHostStorageSmokeTest(self):
|
||||
"""
|
||||
Verify that each storage pool displays, without error.
|
||||
"""
|
||||
win = self.app.open_host_window("Storage")
|
||||
lst = win.find("pool-list", "table")
|
||||
errlabel = win.find("pool-error-label", "label")
|
||||
lib.utils.walkUIList(self.app, win, lst, lambda: errlabel.showing)
|
||||
def testHostNetworkEdit(app):
|
||||
"""
|
||||
Test edits to net config
|
||||
"""
|
||||
app.open(xmleditor_enabled=True)
|
||||
win = app.manager_open_host("Virtual Networks").find("network-grid")
|
||||
finish = win.find("Apply", "push button")
|
||||
|
||||
# Select XML editor, and reverse walk the list
|
||||
win.find("storage-grid").find("XML", "page tab").click()
|
||||
lib.utils.walkUIList(self.app, win, lst, lambda: errlabel.showing, reverse=True)
|
||||
# Shut it off, 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()
|
||||
lib.utils.check(lambda: delete.sensitive)
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
origdev = "virbr0"
|
||||
newdev = "virbr77"
|
||||
xmleditor.set_text(xmleditor.text.replace(origdev, newdev))
|
||||
finish.click()
|
||||
win.find("Details", "page tab").click()
|
||||
netdev = win.find("net-device")
|
||||
lib.utils.check(lambda: netdev.text == newdev)
|
||||
|
||||
def testHostStorageEdit(self):
|
||||
"""
|
||||
Test edits to pool config
|
||||
"""
|
||||
self.app.open(xmleditor_enabled=True)
|
||||
win = self.app.open_host_window("Storage").find("storage-grid")
|
||||
finish = win.find("Apply", "push button")
|
||||
# Rename it
|
||||
win.find("default", "table cell").click()
|
||||
win.find("net-name").set_text("newsort-default")
|
||||
finish.click()
|
||||
|
||||
# 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()
|
||||
lib.utils.check(lambda: delete.sensitive)
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
origpath = "/dev/default-pool"
|
||||
newpath = "/dev/foo/bar/baz"
|
||||
xmleditor.set_text(xmleditor.text.replace(origpath, newpath))
|
||||
finish.click()
|
||||
win.find("Details", "page tab").click()
|
||||
poolloc = win.find("pool-location")
|
||||
lib.utils.check(lambda: poolloc.text == newpath)
|
||||
# Change autostart, trigger it by clicking away
|
||||
win.find("newsort-default", "table cell").click()
|
||||
win.find("net-autostart").click()
|
||||
win.find("netboot", "table cell").click()
|
||||
app.click_alert_button("There are unapplied changes", "Yes")
|
||||
|
||||
# Rename it
|
||||
win.find("default", "table cell").click()
|
||||
win.find("pool-name").set_text("newsort-default")
|
||||
finish.click()
|
||||
# Do standard xmleditor tests
|
||||
lib.utils.test_xmleditor_interactions(app, win, finish)
|
||||
|
||||
# Change autostart. Trigger it by clicking on new cell
|
||||
win.find("newsort-default", "table cell").click()
|
||||
win.find("pool-autostart").click()
|
||||
win.find("disk-pool", "table cell").click()
|
||||
self.app.click_alert_button("There are unapplied changes", "Yes")
|
||||
|
||||
# Do standard xmleditor tests
|
||||
lib.utils.test_xmleditor_interactions(self.app, win, finish)
|
||||
|
||||
def testHostStorageVolMisc(self):
|
||||
"""
|
||||
Misc actions involving volumes
|
||||
"""
|
||||
win = self.app.open_host_window("Storage").find("storage-grid")
|
||||
win.find_fuzzy("default-pool", "table cell").click()
|
||||
vollist = win.find("vol-list", "table")
|
||||
def testHostStorageSmokeTest(app):
|
||||
"""
|
||||
Verify that each storage pool displays, without error.
|
||||
"""
|
||||
win = app.manager_open_host("Storage")
|
||||
lst = win.find("pool-list", "table")
|
||||
errlabel = win.find("pool-error-label", "label")
|
||||
lib.utils.walkUIList(app, win, lst, lambda: errlabel.showing)
|
||||
|
||||
vol1 = vollist.find("backingl1.img", "table cell")
|
||||
vol2 = vollist.find("UPPER", "table cell")
|
||||
vol1.check_onscreen()
|
||||
vol2.check_not_onscreen()
|
||||
win.find("Size", "table column header").click()
|
||||
win.find("Size", "table column header").click()
|
||||
vol1.check_not_onscreen()
|
||||
vol2.check_onscreen()
|
||||
# Select XML editor, and reverse walk the list
|
||||
win.find("storage-grid").find("XML", "page tab").click()
|
||||
lib.utils.walkUIList(app, win, lst, lambda: errlabel.showing, reverse=True)
|
||||
|
||||
vol2.click(button=3)
|
||||
self.app.root.find("Copy Volume Path", "menu item").click()
|
||||
from gi.repository import Gdk, Gtk
|
||||
clipboard = Gtk.Clipboard.get_default(Gdk.Display.get_default())
|
||||
lib.utils.check(lambda: clipboard.wait_for_text() == "/dev/default-pool/UPPER")
|
||||
|
||||
def testHostConn(self):
|
||||
"""
|
||||
Change some connection parameters
|
||||
"""
|
||||
manager = self.app.topwin
|
||||
# Disconnect the connection
|
||||
c = manager.find_fuzzy("testdriver.xml", "table cell")
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-disconnect", "menu item").click()
|
||||
lib.utils.check(lambda: "Not Connected" in c.text)
|
||||
def testHostStorageEdit(app):
|
||||
"""
|
||||
Test edits to pool config
|
||||
"""
|
||||
app.open(xmleditor_enabled=True)
|
||||
win = app.manager_open_host("Storage").find("storage-grid")
|
||||
finish = win.find("Apply", "push button")
|
||||
|
||||
# Open Host Details from right click menu
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-details", "menu item").click()
|
||||
win = self.app.root.find_fuzzy("Connection Details", "frame")
|
||||
# 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()
|
||||
lib.utils.check(lambda: delete.sensitive)
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
origpath = "/dev/default-pool"
|
||||
newpath = "/dev/foo/bar/baz"
|
||||
xmleditor.set_text(xmleditor.text.replace(origpath, newpath))
|
||||
finish.click()
|
||||
win.find("Details", "page tab").click()
|
||||
poolloc = win.find("pool-location")
|
||||
lib.utils.check(lambda: poolloc.text == newpath)
|
||||
|
||||
# Click the tabs and then back
|
||||
win.find_fuzzy("Storage", "tab").click()
|
||||
win.find_fuzzy("Network", "tab").click()
|
||||
win.find_fuzzy("Overview", "tab").click()
|
||||
# Rename it
|
||||
win.find("default", "table cell").click()
|
||||
win.find("pool-name").set_text("newsort-default")
|
||||
finish.click()
|
||||
|
||||
# Toggle autoconnect
|
||||
win.find("Autoconnect:", "check box").click()
|
||||
win.find("Autoconnect:", "check box").click()
|
||||
# Change autostart. Trigger it by clicking on new cell
|
||||
win.find("newsort-default", "table cell").click()
|
||||
win.find("pool-autostart").click()
|
||||
win.find("disk-pool", "table cell").click()
|
||||
app.click_alert_button("There are unapplied changes", "Yes")
|
||||
|
||||
# Change the name, verify that title bar changed
|
||||
win.find("Name:", "text").set_text("FOOBAR")
|
||||
self.app.root.find("FOOBAR - Connection Details", "frame")
|
||||
# Do standard xmleditor tests
|
||||
lib.utils.test_xmleditor_interactions(app, win, finish)
|
||||
|
||||
# Open the manager window
|
||||
win.find("File", "menu").click()
|
||||
win.find("View Manager", "menu item").click()
|
||||
lib.utils.check(lambda: manager.active)
|
||||
# Confirm connection row is named differently in manager
|
||||
manager.find("FOOBAR", "table cell")
|
||||
|
||||
# Close the manager
|
||||
manager.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: win.active)
|
||||
def testHostStorageVolMisc(app):
|
||||
"""
|
||||
Misc actions involving volumes
|
||||
"""
|
||||
win = app.manager_open_host("Storage").find("storage-grid")
|
||||
win.find_fuzzy("default-pool", "table cell").click()
|
||||
vollist = win.find("vol-list", "table")
|
||||
|
||||
# Quit app from the file menu
|
||||
win.find("File", "menu").click()
|
||||
win.find("Quit", "menu item").click()
|
||||
lib.utils.check(lambda: not self.app.is_running())
|
||||
vol1 = vollist.find("backingl1.img", "table cell")
|
||||
vol2 = vollist.find("UPPER", "table cell")
|
||||
vol1.check_onscreen()
|
||||
vol2.check_not_onscreen()
|
||||
win.find("Size", "table column header").click()
|
||||
win.find("Size", "table column header").click()
|
||||
vol1.check_not_onscreen()
|
||||
vol2.check_onscreen()
|
||||
|
||||
vol2.click(button=3)
|
||||
app.root.find("Copy Volume Path", "menu item").click()
|
||||
from gi.repository import Gdk, Gtk
|
||||
clipboard = Gtk.Clipboard.get_default(Gdk.Display.get_default())
|
||||
lib.utils.check(lambda: clipboard.wait_for_text() == "/dev/default-pool/UPPER")
|
||||
|
||||
|
||||
def testHostConn(app):
|
||||
"""
|
||||
Change some connection parameters
|
||||
"""
|
||||
manager = app.topwin
|
||||
# Disconnect the connection
|
||||
app.manager_conn_disconnect("test testdriver.xml")
|
||||
|
||||
# Open Host Details from right click menu
|
||||
c = manager.find("test testdriver.xml", "table cell")
|
||||
c.click(button=3)
|
||||
app.root.find("conn-details", "menu item").click()
|
||||
win = app.find_window("test testdriver.xml - Connection Details")
|
||||
|
||||
# Click the tabs and then back
|
||||
win.find_fuzzy("Storage", "tab").click()
|
||||
win.find_fuzzy("Network", "tab").click()
|
||||
win.find_fuzzy("Overview", "tab").click()
|
||||
|
||||
# Toggle autoconnect
|
||||
win.find("Autoconnect:", "check box").click()
|
||||
win.find("Autoconnect:", "check box").click()
|
||||
|
||||
# Change the name, verify that title bar changed
|
||||
win.find("Name:", "text").set_text("FOOBAR")
|
||||
app.find_window("FOOBAR - Connection Details")
|
||||
|
||||
# Open the manager window
|
||||
win.find("File", "menu").click()
|
||||
win.find("View Manager", "menu item").click()
|
||||
lib.utils.check(lambda: manager.active)
|
||||
# Confirm connection row is named differently in manager
|
||||
manager.find("FOOBAR", "table cell")
|
||||
|
||||
# Close the manager
|
||||
manager.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: win.active)
|
||||
|
||||
# Quit app from the file menu
|
||||
win.find("File", "menu").click()
|
||||
win.find("Quit", "menu item").click()
|
||||
lib.utils.check(lambda: not app.is_running())
|
||||
|
|
|
@ -13,60 +13,48 @@ except Exception:
|
|||
HAS_LIBGUESTFS = False
|
||||
|
||||
|
||||
class VMMInspection(lib.testcase.UITestCase):
|
||||
"""
|
||||
UI tests for the libguestfs inspection infrastructure
|
||||
"""
|
||||
#########################################################
|
||||
# UI tests for the libguestfs inspection infrastructure #
|
||||
#########################################################
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
def testInspectionMock(app):
|
||||
if not HAS_LIBGUESTFS:
|
||||
pytest.skip("libguestfs python not installed")
|
||||
|
||||
def testInspectionMock(self):
|
||||
if not HAS_LIBGUESTFS:
|
||||
pytest.skip("libguestfs python not installed")
|
||||
# Use the test suite inspection mocking to test parts
|
||||
# of the UI that interact with inspection data
|
||||
app.open(enable_libguestfs=True)
|
||||
manager = app.topwin
|
||||
|
||||
# Use the test suite inspection mocking to test parts
|
||||
# of the UI that interact with inspection data
|
||||
self.app.open(enable_libguestfs=True)
|
||||
manager = self.app.topwin
|
||||
details = app.manager_open_details("test-clone")
|
||||
details.find("OS information", "table cell").click()
|
||||
tab = details.find("os-tab")
|
||||
|
||||
details = self.app.open_details_window("test-clone")
|
||||
details.find("OS information", "table cell").click()
|
||||
tab = details.find("os-tab")
|
||||
tab.find("Application", "toggle").click_expander()
|
||||
apps = tab.find("inspection-apps")
|
||||
apps.check_onscreen()
|
||||
apps.click_expander()
|
||||
|
||||
tab.find("Application", "toggle").click_expander()
|
||||
apps = tab.find("inspection-apps")
|
||||
apps.check_onscreen()
|
||||
apps.click_expander()
|
||||
nodestr1 = apps.fmt_nodes()
|
||||
assert "test_app1_summary" in nodestr1
|
||||
tab.find("Refresh", "push button").click()
|
||||
lib.utils.check(lambda: apps.fmt_nodes() != nodestr1)
|
||||
|
||||
nodestr1 = apps.fmt_nodes()
|
||||
assert "test_app1_summary" in nodestr1
|
||||
tab.find("Refresh", "push button").click()
|
||||
lib.utils.check(lambda: apps.fmt_nodes() != nodestr1)
|
||||
details.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: not details.showing)
|
||||
|
||||
details.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: not details.showing)
|
||||
# Open a VM with no disks which will report an inspection error
|
||||
app.root.find_fuzzy("test\n", "table cell").doubleClick()
|
||||
details = app.find_window("test on")
|
||||
details.find("Details", "radio button").click()
|
||||
details.find("OS information", "table cell").click()
|
||||
tab = details.find("os-tab")
|
||||
tab.find_fuzzy("Fake test error no disks")
|
||||
|
||||
# Open a VM with no disks which will report an inspection error
|
||||
self.app.root.find_fuzzy("test\n", "table cell").doubleClick()
|
||||
details = self.app.root.find("test on", "frame")
|
||||
details.find("Details", "radio button").click()
|
||||
details.find("OS information", "table cell").click()
|
||||
tab = details.find("os-tab")
|
||||
tab.find_fuzzy("Fake test error no disks")
|
||||
|
||||
# Closing and reopening a connection triggers some libguest
|
||||
# cache reading
|
||||
details.keyCombo("<alt>F4")
|
||||
manager.click()
|
||||
c = manager.find_fuzzy("testdriver.xml", "table cell")
|
||||
c.click()
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-disconnect", "menu item").click()
|
||||
manager.click()
|
||||
c = manager.find_fuzzy("testdriver.xml", "table cell")
|
||||
c.click()
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-connect", "menu item").click()
|
||||
self.app.sleep(2)
|
||||
# Closing and reopening a connection triggers some libguest
|
||||
# cache reading
|
||||
details.keyCombo("<alt>F4")
|
||||
manager.click()
|
||||
app.manager_conn_disconnect("test testdriver.xml")
|
||||
app.manager_conn_connect("test testdriver.xml")
|
||||
app.sleep(2)
|
||||
|
|
|
@ -16,24 +16,24 @@ def _vm_wrapper(vmname, uri="qemu:///system", opts=None):
|
|||
Decorator to define+start a VM and clean it up on exit
|
||||
"""
|
||||
def wrap1(fn):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
self.app.error_if_already_running()
|
||||
def wrapper(app, *args, **kwargs):
|
||||
app.error_if_already_running()
|
||||
xmlfile = "%s/live/%s.xml" % (tests.utils.UITESTDATADIR, vmname)
|
||||
conn = libvirt.open(uri)
|
||||
dom = conn.defineXML(open(xmlfile).read())
|
||||
try:
|
||||
dom.create()
|
||||
self.app.uri = uri
|
||||
self.conn = conn
|
||||
app.uri = uri
|
||||
app.conn = conn
|
||||
extra_opts = (opts or [])
|
||||
extra_opts += ["--show-domain-console", vmname]
|
||||
# Enable stats for more code coverage
|
||||
keyfile = "statsonly.ini"
|
||||
self.app.open(extra_opts=extra_opts, keyfile=keyfile)
|
||||
fn(self, dom, *args, **kwargs)
|
||||
app.open(extra_opts=extra_opts, keyfile=keyfile)
|
||||
fn(app, dom, *args, **kwargs)
|
||||
finally:
|
||||
try:
|
||||
self.app.stop()
|
||||
app.stop()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
|
@ -45,399 +45,404 @@ def _vm_wrapper(vmname, uri="qemu:///system", opts=None):
|
|||
return wrap1
|
||||
|
||||
|
||||
class Console(lib.testcase.UITestCase):
|
||||
def _destroy(app, win):
|
||||
smenu = win.find("Menu", "toggle button")
|
||||
smenu.click()
|
||||
smenu.find("Force Off", "menu item").click()
|
||||
app.click_alert_button("you sure", "Yes")
|
||||
run = win.find("Run", "push button")
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
|
||||
|
||||
###############################################
|
||||
# Test live console connections with stub VMs #
|
||||
###############################################
|
||||
|
||||
def _checkConsoleStandard(app, dom):
|
||||
"""
|
||||
Test live console connections with stub VMs
|
||||
Shared logic for general console handling
|
||||
"""
|
||||
win = app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
conn = None
|
||||
extraopts = None
|
||||
win.find("Virtual Machine", "menu").click()
|
||||
win.find("Take Screenshot", "menu item").click()
|
||||
chooser = app.root.find(None, "file chooser")
|
||||
fname = chooser.find("Name", "text").text
|
||||
app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: os.path.exists(fname))
|
||||
os.unlink(fname)
|
||||
lib.utils.check(lambda: win.active)
|
||||
|
||||
def _destroy(self, win):
|
||||
smenu = win.find("Menu", "toggle button")
|
||||
smenu.click()
|
||||
smenu.find("Force Off", "menu item").click()
|
||||
self.app.click_alert_button("you sure", "Yes")
|
||||
run = win.find("Run", "push button")
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
win.find("Send Key", "menu").click()
|
||||
win.find(r"Ctrl\+Alt\+F1", "menu item").click()
|
||||
win.find("Send Key", "menu").click()
|
||||
win.find(r"Ctrl\+Alt\+F10", "menu item").click()
|
||||
win.find("Send Key", "menu").click()
|
||||
win.find(r"Ctrl\+Alt\+Delete", "menu item").click()
|
||||
|
||||
# 'Resize to VM' testing
|
||||
oldsize = win.size
|
||||
win.find("^View$", "menu").click()
|
||||
win.find("Resize to VM", "menu item").click()
|
||||
newsize = win.size
|
||||
lib.utils.check(lambda: oldsize != newsize)
|
||||
|
||||
# Fullscreen testing
|
||||
win.find("^View$", "menu").click()
|
||||
win.find("Fullscreen", "check menu item").click()
|
||||
fstb = win.find("Fullscreen Toolbar")
|
||||
lib.utils.check(lambda: fstb.showing)
|
||||
lib.utils.check(lambda: win.size != newsize)
|
||||
|
||||
# Wait for toolbar to hide, then reveal it again
|
||||
lib.utils.check(lambda: not fstb.showing, timeout=5)
|
||||
app.rawinput.point(win.position[0] + win.size[0] / 2, 0)
|
||||
lib.utils.check(lambda: fstb.showing)
|
||||
# Move it off and have it hide again
|
||||
win.point()
|
||||
lib.utils.check(lambda: not fstb.showing, timeout=5)
|
||||
app.rawinput.point(win.position[0] + win.size[0] / 2, 0)
|
||||
lib.utils.check(lambda: fstb.showing)
|
||||
|
||||
# Click stuff and exit fullscreen
|
||||
win.find("Fullscreen Send Key").click()
|
||||
app.rawinput.pressKey("Escape")
|
||||
win.find("Fullscreen Exit").click()
|
||||
lib.utils.check(lambda: win.size == newsize)
|
||||
|
||||
# Trigger pointer grab, verify title was updated
|
||||
win.click()
|
||||
lib.utils.check(lambda: "Control_L" in win.name)
|
||||
# Ungrab
|
||||
win.keyCombo("<ctrl><alt>")
|
||||
lib.utils.check(lambda: "Control_L" not in win.name)
|
||||
|
||||
# Tweak scaling
|
||||
win.window_maximize()
|
||||
win.find("^View$", "menu").click()
|
||||
scalemenu = win.find("Scale Display", "menu")
|
||||
scalemenu.point()
|
||||
scalemenu.find("Always", "radio menu item").click()
|
||||
win.find("^View$", "menu").click()
|
||||
scalemenu = win.find("Scale Display", "menu")
|
||||
scalemenu.point()
|
||||
scalemenu.find("Never", "radio menu item").click()
|
||||
win.find("^View$", "menu").click()
|
||||
scalemenu = win.find("Scale Display", "menu")
|
||||
scalemenu.point()
|
||||
scalemenu.find("Only", "radio menu item").click()
|
||||
|
||||
# Check that modifiers don't work
|
||||
win.click()
|
||||
app.sleep(1)
|
||||
win.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: win.showing)
|
||||
dom.destroy()
|
||||
win.find("Guest is not running.")
|
||||
win.click_title()
|
||||
app.sleep(1)
|
||||
win.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
@_vm_wrapper("uitests-vnc-standard")
|
||||
def testConsoleVNCStandard(app, dom):
|
||||
return _checkConsoleStandard(app, dom)
|
||||
|
||||
def _checkConsoleStandard(self, dom):
|
||||
"""
|
||||
Shared logic for general console handling
|
||||
"""
|
||||
win = self.app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
win.find("Virtual Machine", "menu").click()
|
||||
win.find("Take Screenshot", "menu item").click()
|
||||
chooser = self.app.root.find(None, "file chooser")
|
||||
fname = chooser.find("Name", "text").text
|
||||
self.app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: os.path.exists(fname))
|
||||
os.unlink(fname)
|
||||
lib.utils.check(lambda: win.active)
|
||||
@_vm_wrapper("uitests-spice-standard")
|
||||
def testConsoleSpiceStandard(app, dom):
|
||||
return _checkConsoleStandard(app, dom)
|
||||
|
||||
win.find("Send Key", "menu").click()
|
||||
win.find(r"Ctrl\+Alt\+F1", "menu item").click()
|
||||
win.find("Send Key", "menu").click()
|
||||
win.find(r"Ctrl\+Alt\+F10", "menu item").click()
|
||||
win.find("Send Key", "menu").click()
|
||||
win.find(r"Ctrl\+Alt\+Delete", "menu item").click()
|
||||
|
||||
# 'Resize to VM' testing
|
||||
oldsize = win.size
|
||||
win.find("^View$", "menu").click()
|
||||
win.find("Resize to VM", "menu item").click()
|
||||
newsize = win.size
|
||||
lib.utils.check(lambda: oldsize != newsize)
|
||||
def _checkPassword(app):
|
||||
"""
|
||||
Shared logic for password handling
|
||||
"""
|
||||
win = app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: not con.showing)
|
||||
passwd = win.find("Password:", "password text")
|
||||
lib.utils.check(lambda: passwd.showing)
|
||||
|
||||
# Fullscreen testing
|
||||
win.find("^View$", "menu").click()
|
||||
win.find("Fullscreen", "check menu item").click()
|
||||
fstb = win.find("Fullscreen Toolbar")
|
||||
lib.utils.check(lambda: fstb.showing)
|
||||
lib.utils.check(lambda: win.size != newsize)
|
||||
|
||||
# Wait for toolbar to hide, then reveal it again
|
||||
lib.utils.check(lambda: not fstb.showing, timeout=5)
|
||||
self.app.rawinput.point(win.position[0] + win.size[0] / 2, 0)
|
||||
lib.utils.check(lambda: fstb.showing)
|
||||
# Move it off and have it hide again
|
||||
win.point()
|
||||
lib.utils.check(lambda: not fstb.showing, timeout=5)
|
||||
self.app.rawinput.point(win.position[0] + win.size[0] / 2, 0)
|
||||
lib.utils.check(lambda: fstb.showing)
|
||||
|
||||
# Click stuff and exit fullscreen
|
||||
win.find("Fullscreen Send Key").click()
|
||||
self.app.rawinput.pressKey("Escape")
|
||||
win.find("Fullscreen Exit").click()
|
||||
lib.utils.check(lambda: win.size == newsize)
|
||||
|
||||
# Trigger pointer grab, verify title was updated
|
||||
win.click()
|
||||
lib.utils.check(lambda: "Control_L" in win.name)
|
||||
# Ungrab
|
||||
win.keyCombo("<ctrl><alt>")
|
||||
lib.utils.check(lambda: "Control_L" not in win.name)
|
||||
|
||||
# Tweak scaling
|
||||
win.click_title()
|
||||
win.click_title()
|
||||
win.find("^View$", "menu").click()
|
||||
scalemenu = win.find("Scale Display", "menu")
|
||||
scalemenu.point()
|
||||
scalemenu.find("Always", "radio menu item").click()
|
||||
win.find("^View$", "menu").click()
|
||||
scalemenu = win.find("Scale Display", "menu")
|
||||
scalemenu.point()
|
||||
scalemenu.find("Never", "radio menu item").click()
|
||||
win.find("^View$", "menu").click()
|
||||
scalemenu = win.find("Scale Display", "menu")
|
||||
scalemenu.point()
|
||||
scalemenu.find("Only", "radio menu item").click()
|
||||
|
||||
# Check that modifiers don't work
|
||||
win.click()
|
||||
self.app.sleep(1)
|
||||
win.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: win.showing)
|
||||
dom.destroy()
|
||||
win.find("Guest is not running.")
|
||||
win.click_title()
|
||||
self.app.sleep(1)
|
||||
win.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
@_vm_wrapper("uitests-vnc-standard")
|
||||
def testConsoleVNCStandard(self, dom):
|
||||
return self._checkConsoleStandard(dom)
|
||||
@_vm_wrapper("uitests-spice-standard")
|
||||
def testConsoleSpiceStandard(self, dom):
|
||||
return self._checkConsoleStandard(dom)
|
||||
|
||||
def _checkPassword(self):
|
||||
"""
|
||||
Shared logic for password handling
|
||||
"""
|
||||
win = self.app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: not con.showing)
|
||||
passwd = win.find("Password:", "password text")
|
||||
lib.utils.check(lambda: passwd.showing)
|
||||
|
||||
# Check wrong password handling
|
||||
passwd.typeText("xx")
|
||||
win.find("Login", "push button").click()
|
||||
self.app.click_alert_button("Viewer authentication error", "OK")
|
||||
savecheck = win.find("Save this password", "check box")
|
||||
if not savecheck.checked:
|
||||
savecheck.click()
|
||||
passwd.typeText("yy")
|
||||
self.app.rawinput.pressKey("Enter")
|
||||
self.app.click_alert_button("Viewer authentication error", "OK")
|
||||
|
||||
# Check proper password
|
||||
passwd.text = ""
|
||||
passwd.typeText("goodp")
|
||||
win.find("Login", "push button").click()
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
# Restart VM to retrigger console connect
|
||||
self._destroy(win)
|
||||
win.find("Run", "push button").click()
|
||||
lib.utils.check(lambda: passwd.showing)
|
||||
# Password should be filled in
|
||||
lib.utils.check(lambda: bool(passwd.text))
|
||||
# Uncheck 'Save password' and login, which will delete it from keyring
|
||||
# Check wrong password handling
|
||||
passwd.typeText("xx")
|
||||
win.find("Login", "push button").click()
|
||||
app.click_alert_button("Viewer authentication error", "OK")
|
||||
savecheck = win.find("Save this password", "check box")
|
||||
if not savecheck.checked:
|
||||
savecheck.click()
|
||||
win.find("Login", "push button").click()
|
||||
lib.utils.check(lambda: con.showing)
|
||||
passwd.typeText("yy")
|
||||
app.rawinput.pressKey("Enter")
|
||||
app.click_alert_button("Viewer authentication error", "OK")
|
||||
|
||||
# Restart VM to retrigger console connect
|
||||
self._destroy(win)
|
||||
win.find("Run", "push button").click()
|
||||
lib.utils.check(lambda: passwd.showing)
|
||||
# Password should be empty now
|
||||
lib.utils.check(lambda: not bool(passwd.text))
|
||||
# Check proper password
|
||||
passwd.text = ""
|
||||
passwd.typeText("goodp")
|
||||
win.find("Login", "push button").click()
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
@_vm_wrapper("uitests-vnc-password")
|
||||
def testConsoleVNCPassword(self, dom):
|
||||
ignore = dom
|
||||
return self._checkPassword()
|
||||
@_vm_wrapper("uitests-spice-password")
|
||||
def testConsoleSpicePassword(self, dom):
|
||||
ignore = dom
|
||||
return self._checkPassword()
|
||||
# Restart VM to retrigger console connect
|
||||
_destroy(app, win)
|
||||
win.find("Run", "push button").click()
|
||||
lib.utils.check(lambda: passwd.showing)
|
||||
# Password should be filled in
|
||||
lib.utils.check(lambda: bool(passwd.text))
|
||||
# Uncheck 'Save password' and login, which will delete it from keyring
|
||||
savecheck.click()
|
||||
win.find("Login", "push button").click()
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
@_vm_wrapper("uitests-vnc-password",
|
||||
opts=["--test-options=fake-vnc-username"])
|
||||
def testConsoleVNCPasswordUsername(self, dom):
|
||||
ignore = dom
|
||||
win = self.app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: not con.showing)
|
||||
passwd = win.find("Password:", "password text")
|
||||
lib.utils.check(lambda: passwd.showing)
|
||||
username = win.find("Username:", "text")
|
||||
lib.utils.check(lambda: username.showing)
|
||||
# Restart VM to retrigger console connect
|
||||
_destroy(app, win)
|
||||
win.find("Run", "push button").click()
|
||||
lib.utils.check(lambda: passwd.showing)
|
||||
# Password should be empty now
|
||||
lib.utils.check(lambda: not bool(passwd.text))
|
||||
|
||||
# Since we are mocking the username, sending the credentials
|
||||
# is ignored, so with the correct password this succeeds
|
||||
username.text = "fakeuser"
|
||||
passwd.typeText("goodp")
|
||||
win.find("Login", "push button").click()
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
@_vm_wrapper("uitests-vnc-socket")
|
||||
def testConsoleVNCSocket(self, dom):
|
||||
ignore = dom
|
||||
win = self.app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: con.showing)
|
||||
@_vm_wrapper("uitests-vnc-password")
|
||||
def testConsoleVNCPassword(app, dom):
|
||||
ignore = dom
|
||||
return _checkPassword(app)
|
||||
|
||||
def _click_textconsole_menu(msg):
|
||||
vmenu = win.find("^View$", "menu")
|
||||
vmenu.click()
|
||||
tmenu = win.find("Consoles", "menu")
|
||||
tmenu.point()
|
||||
tmenu.find(msg, "radio menu item").click()
|
||||
|
||||
# A bit of an extra test, make sure selecting Graphical Console works
|
||||
_click_textconsole_menu("Serial 1")
|
||||
lib.utils.check(lambda: not con.showing)
|
||||
_click_textconsole_menu("Graphical Console")
|
||||
lib.utils.check(lambda: con.showing)
|
||||
@_vm_wrapper("uitests-spice-password")
|
||||
def testConsoleSpicePassword(app, dom):
|
||||
ignore = dom
|
||||
return _checkPassword(app)
|
||||
|
||||
@_vm_wrapper("uitests-spice-standard")
|
||||
def testConsoleAutoconnect(self, dom):
|
||||
ignore = dom
|
||||
win = self.app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
# Disable autoconnect
|
||||
@_vm_wrapper("uitests-vnc-password",
|
||||
opts=["--test-options=fake-vnc-username"])
|
||||
def testConsoleVNCPasswordUsername(app, dom):
|
||||
ignore = dom
|
||||
win = app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: not con.showing)
|
||||
passwd = win.find("Password:", "password text")
|
||||
lib.utils.check(lambda: passwd.showing)
|
||||
username = win.find("Username:", "text")
|
||||
lib.utils.check(lambda: username.showing)
|
||||
|
||||
# Since we are mocking the username, sending the credentials
|
||||
# is ignored, so with the correct password this succeeds
|
||||
username.text = "fakeuser"
|
||||
passwd.typeText("goodp")
|
||||
win.find("Login", "push button").click()
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
|
||||
@_vm_wrapper("uitests-vnc-socket")
|
||||
def testConsoleVNCSocket(app, dom):
|
||||
ignore = dom
|
||||
win = app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
def _click_textconsole_menu(msg):
|
||||
vmenu = win.find("^View$", "menu")
|
||||
vmenu.click()
|
||||
vmenu.find("Autoconnect").click()
|
||||
dom.destroy()
|
||||
self.app.sleep(1)
|
||||
dom.create()
|
||||
lib.utils.check(lambda: not con.showing)
|
||||
win.find("Connect to console", "push button").click()
|
||||
lib.utils.check(lambda: con.showing)
|
||||
tmenu = win.find("Consoles", "menu")
|
||||
tmenu.point()
|
||||
# We need to sleep to give the menu time to dynamically populate
|
||||
app.sleep(.5)
|
||||
tmenu.find(msg, "radio menu item").click()
|
||||
|
||||
@_vm_wrapper("uitests-lxc-serial", uri="lxc:///")
|
||||
def testConsoleLXCSerial(self, dom):
|
||||
"""
|
||||
Ensure LXC has serial open, and we can send some data
|
||||
"""
|
||||
ignore = dom
|
||||
win = self.app.topwin
|
||||
term = win.find("Serial Terminal")
|
||||
lib.utils.check(lambda: term.showing)
|
||||
term.typeText("help\n")
|
||||
lib.utils.check(lambda: "COMMANDS" in term.text)
|
||||
|
||||
term.doubleClick()
|
||||
term.click(button=3)
|
||||
menu = self.app.root.find("serial-popup-menu")
|
||||
menu.find("Copy", "menu item").click()
|
||||
|
||||
term.click()
|
||||
term.click(button=3)
|
||||
menu = self.app.root.find("serial-popup-menu")
|
||||
menu.find("Paste", "menu item").click()
|
||||
|
||||
win.find("Details", "radio button").click()
|
||||
win.find("Console", "radio button").click()
|
||||
self._destroy(win)
|
||||
view = self.app.root.find("^View$", "menu")
|
||||
view.click()
|
||||
# Triggers some tooltip cases
|
||||
textmenu = view.find("Consoles", "menu")
|
||||
textmenu.point()
|
||||
lib.utils.check(lambda: textmenu.showing)
|
||||
item = textmenu.find("Text Console 1")
|
||||
lib.utils.check(lambda: not item.sensitive)
|
||||
|
||||
# Restart the guest to trigger reconnect code
|
||||
view.click()
|
||||
win.find("Run", "push button").click()
|
||||
term = win.find("Serial Terminal")
|
||||
lib.utils.check(lambda: term.showing)
|
||||
|
||||
# Ensure ctrl+w doesn't close the window, modifiers are disabled
|
||||
term.click()
|
||||
win.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: win.showing)
|
||||
# Shut it down, ensure <ctrl>w works again
|
||||
self._destroy(win)
|
||||
win.click_title()
|
||||
self.app.sleep(1)
|
||||
win.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
# A bit of an extra test, make sure selecting Graphical Console works
|
||||
_click_textconsole_menu("Serial 1")
|
||||
lib.utils.check(lambda: not con.showing)
|
||||
_click_textconsole_menu("Graphical Console")
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
|
||||
@_vm_wrapper("uitests-spice-specific",
|
||||
opts=["--test-options=spice-agent",
|
||||
"--test-options=fake-console-resolution"])
|
||||
def testConsoleSpiceSpecific(self, dom):
|
||||
"""
|
||||
Spice specific behavior. Has lots of devices that will open
|
||||
channels, spice GL + local config, and usbredir
|
||||
"""
|
||||
ignore = dom
|
||||
win = self.app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: con.showing)
|
||||
@_vm_wrapper("uitests-spice-standard")
|
||||
def testConsoleAutoconnect(app, dom):
|
||||
ignore = dom
|
||||
win = app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
# Just ensure the dialog pops up, can't really test much more
|
||||
# than that
|
||||
win.find("Virtual Machine", "menu").click()
|
||||
win.find("Redirect USB", "menu item").click()
|
||||
|
||||
usbwin = self.app.root.find("vmm dialog", "alert")
|
||||
usbwin.find("Select USB devices for redirection", "label")
|
||||
usbwin.find("SPICE CD", "check box").click()
|
||||
chooser = self.app.root.find(None, "file chooser")
|
||||
# Find the cwd bookmark on the left
|
||||
chooser.find("virt-manager", "label").click()
|
||||
chooser.find("virt-manager", "label").click()
|
||||
chooser.find("COPYING").click()
|
||||
self.app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: not chooser.showing)
|
||||
usbwin.find("Close", "push button").click()
|
||||
|
||||
# Test fake guest resize behavior
|
||||
def _click_auto():
|
||||
vmenu = win.find("^View$", "menu")
|
||||
vmenu.click()
|
||||
smenu = vmenu.find("Scale Display", "menu")
|
||||
smenu.point()
|
||||
smenu.find("Auto resize VM", "check menu item").click()
|
||||
_click_auto()
|
||||
win.click_title()
|
||||
win.click_title()
|
||||
_click_auto()
|
||||
win.click_title()
|
||||
win.click_title()
|
||||
|
||||
def _testLiveHotplug(self, fname):
|
||||
win = self.app.topwin
|
||||
win.find("Details", "radio button").click()
|
||||
|
||||
# Add a scsi disk, importing the passed path
|
||||
win.find("add-hardware", "push button").click()
|
||||
addhw = self.app.root.find("Add New Virtual Hardware", "frame")
|
||||
addhw.find("Storage", "table cell").click()
|
||||
tab = addhw.find("storage-tab", None)
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
tab.find("Select or create", "radio button").click()
|
||||
tab.find("storage-entry").set_text(fname)
|
||||
tab.combo_select("Bus type:", "SCSI")
|
||||
addhw.find("Finish", "push button").click()
|
||||
|
||||
# Verify permission dialog pops up, ask to change
|
||||
self.app.click_alert_button(
|
||||
"The emulator may not have search permissions", "Yes")
|
||||
|
||||
# Verify no errors
|
||||
lib.utils.check(lambda: not addhw.showing)
|
||||
lib.utils.check(lambda: win.active)
|
||||
|
||||
# Hot unplug the disk
|
||||
win.find("SCSI Disk 1", "table cell").click()
|
||||
tab = win.find("disk-tab", None)
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
win.find("config-remove").click()
|
||||
delete = self.app.root.find_fuzzy("Remove Disk", "frame")
|
||||
delete.find_fuzzy("Delete", "button").click()
|
||||
lib.utils.check(lambda: not delete.active)
|
||||
lib.utils.check(lambda: os.path.exists(fname))
|
||||
|
||||
# Change CDROM
|
||||
win.find("IDE CDROM 1", "table cell").click()
|
||||
tab = win.find("disk-tab", None)
|
||||
entry = win.find("media-entry")
|
||||
appl = win.find("config-apply")
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
entry.set_text(fname)
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: entry.text == fname)
|
||||
entry.click_secondary_icon()
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
# Disable autoconnect
|
||||
vmenu = win.find("^View$", "menu")
|
||||
vmenu.click()
|
||||
vmenu.find("Autoconnect").click()
|
||||
dom.destroy()
|
||||
app.sleep(1)
|
||||
dom.create()
|
||||
lib.utils.check(lambda: not con.showing)
|
||||
win.find("Connect to console", "push button").click()
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
|
||||
@_vm_wrapper("uitests-hotplug")
|
||||
def testLiveHotplug(self, dom):
|
||||
"""
|
||||
Live test for basic hotplugging and media change, as well as
|
||||
testing our auto-poolify magic
|
||||
"""
|
||||
ignore = dom
|
||||
import tempfile
|
||||
tmpdir = tempfile.TemporaryDirectory(prefix="uitests-tmp")
|
||||
dname = tmpdir.name
|
||||
@_vm_wrapper("uitests-lxc-serial", uri="lxc:///")
|
||||
def testConsoleLXCSerial(app, dom):
|
||||
"""
|
||||
Ensure LXC has serial open, and we can send some data
|
||||
"""
|
||||
ignore = dom
|
||||
win = app.topwin
|
||||
term = win.find("Serial Terminal")
|
||||
lib.utils.check(lambda: term.showing)
|
||||
term.typeText("help\n")
|
||||
lib.utils.check(lambda: "COMMANDS" in term.text)
|
||||
|
||||
term.doubleClick()
|
||||
term.click(button=3)
|
||||
menu = app.root.find("serial-popup-menu")
|
||||
menu.find("Copy", "menu item").click()
|
||||
|
||||
term.click()
|
||||
term.click(button=3)
|
||||
menu = app.root.find("serial-popup-menu")
|
||||
menu.find("Paste", "menu item").click()
|
||||
|
||||
win.find("Details", "radio button").click()
|
||||
win.find("Console", "radio button").click()
|
||||
_destroy(app, win)
|
||||
view = app.root.find("^View$", "menu")
|
||||
view.click()
|
||||
# Triggers some tooltip cases
|
||||
textmenu = view.find("Consoles", "menu")
|
||||
textmenu.point()
|
||||
lib.utils.check(lambda: textmenu.showing)
|
||||
app.sleep(.5)
|
||||
item = textmenu.find("Text Console 1")
|
||||
lib.utils.check(lambda: not item.sensitive)
|
||||
|
||||
# Restart the guest to trigger reconnect code
|
||||
view.click()
|
||||
win.find("Run", "push button").click()
|
||||
term = win.find("Serial Terminal")
|
||||
lib.utils.check(lambda: term.showing)
|
||||
|
||||
# Ensure ctrl+w doesn't close the window, modifiers are disabled
|
||||
term.click()
|
||||
win.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: win.showing)
|
||||
# Shut it down, ensure <ctrl>w works again
|
||||
_destroy(app, win)
|
||||
win.click_title()
|
||||
app.sleep(1)
|
||||
win.keyCombo("<ctrl>w")
|
||||
lib.utils.check(lambda: not win.showing)
|
||||
|
||||
|
||||
@_vm_wrapper("uitests-spice-specific",
|
||||
opts=["--test-options=spice-agent",
|
||||
"--test-options=fake-console-resolution"])
|
||||
def testConsoleSpiceSpecific(app, dom):
|
||||
"""
|
||||
Spice specific behavior. Has lots of devices that will open
|
||||
channels, spice GL + local config, and usbredir
|
||||
"""
|
||||
ignore = dom
|
||||
win = app.topwin
|
||||
con = win.find("console-gfx-viewport")
|
||||
lib.utils.check(lambda: con.showing)
|
||||
|
||||
# Just ensure the dialog pops up, can't really test much more
|
||||
# than that
|
||||
win.find("Virtual Machine", "menu").click()
|
||||
win.find("Redirect USB", "menu item").click()
|
||||
|
||||
usbwin = app.root.find("vmm dialog", "alert")
|
||||
usbwin.find("Select USB devices for redirection", "label")
|
||||
usbwin.find("SPICE CD", "check box").click()
|
||||
chooser = app.root.find(None, "file chooser")
|
||||
# Find the cwd bookmark on the left
|
||||
chooser.find("virt-manager", "label").click()
|
||||
chooser.find("virt-manager", "label").click()
|
||||
chooser.find("COPYING").click()
|
||||
app.rawinput.pressKey("Enter")
|
||||
lib.utils.check(lambda: not chooser.showing)
|
||||
usbwin.find("Close", "push button").click()
|
||||
|
||||
# Test fake guest resize behavior
|
||||
def _click_auto():
|
||||
vmenu = win.find("^View$", "menu")
|
||||
vmenu.click()
|
||||
smenu = vmenu.find("Scale Display", "menu")
|
||||
smenu.point()
|
||||
smenu.find("Auto resize VM", "check menu item").click()
|
||||
_click_auto()
|
||||
win.window_maximize()
|
||||
_click_auto()
|
||||
win.click_title()
|
||||
win.click_title()
|
||||
|
||||
|
||||
def _testLiveHotplug(app, fname):
|
||||
win = app.topwin
|
||||
win.find("Details", "radio button").click()
|
||||
|
||||
# Add a scsi disk, importing the passed path
|
||||
win.find("add-hardware", "push button").click()
|
||||
addhw = app.find_window("Add New Virtual Hardware")
|
||||
addhw.find("Storage", "table cell").click()
|
||||
tab = addhw.find("storage-tab", None)
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
tab.find("Select or create", "radio button").click()
|
||||
tab.find("storage-entry").set_text(fname)
|
||||
tab.combo_select("Bus type:", "SCSI")
|
||||
addhw.find("Finish", "push button").click()
|
||||
|
||||
# Verify permission dialog pops up, ask to change
|
||||
app.click_alert_button(
|
||||
"The emulator may not have search permissions", "Yes")
|
||||
|
||||
# Verify no errors
|
||||
lib.utils.check(lambda: not addhw.showing)
|
||||
lib.utils.check(lambda: win.active)
|
||||
|
||||
# Hot unplug the disk
|
||||
win.find("SCSI Disk 1", "table cell").click()
|
||||
tab = win.find("disk-tab", None)
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
win.find("config-remove").click()
|
||||
delete = app.find_window("Remove Disk")
|
||||
delete.find_fuzzy("Delete", "button").click()
|
||||
lib.utils.check(lambda: not delete.active)
|
||||
lib.utils.check(lambda: os.path.exists(fname))
|
||||
|
||||
# Change CDROM
|
||||
win.find("IDE CDROM 1", "table cell").click()
|
||||
tab = win.find("disk-tab", None)
|
||||
entry = win.find("media-entry")
|
||||
appl = win.find("config-apply")
|
||||
lib.utils.check(lambda: tab.showing)
|
||||
entry.set_text(fname)
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: entry.text == fname)
|
||||
entry.click_secondary_icon()
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
|
||||
|
||||
@_vm_wrapper("uitests-hotplug")
|
||||
def testLiveHotplug(app, dom):
|
||||
"""
|
||||
Live test for basic hotplugging and media change, as well as
|
||||
testing our auto-poolify magic
|
||||
"""
|
||||
ignore = dom
|
||||
import tempfile
|
||||
tmpdir = tempfile.TemporaryDirectory(prefix="uitests-tmp")
|
||||
dname = tmpdir.name
|
||||
try:
|
||||
fname = os.path.join(dname, "test.img")
|
||||
os.system("qemu-img create -f qcow2 %s 1M > /dev/null" % fname)
|
||||
os.system("chmod 700 %s" % dname)
|
||||
_testLiveHotplug(app, fname)
|
||||
finally:
|
||||
poolname = os.path.basename(dname)
|
||||
try:
|
||||
fname = os.path.join(dname, "test.img")
|
||||
os.system("qemu-img create -f qcow2 %s 1M > /dev/null" % fname)
|
||||
os.system("chmod 700 %s" % dname)
|
||||
self._testLiveHotplug(fname)
|
||||
finally:
|
||||
poolname = os.path.basename(dname)
|
||||
try:
|
||||
pool = self.conn.storagePoolLookupByName(poolname)
|
||||
pool.destroy()
|
||||
pool.undefine()
|
||||
except Exception:
|
||||
log.debug("Error cleaning up pool", exc_info=True)
|
||||
pool = app.conn.storagePoolLookupByName(poolname)
|
||||
pool.destroy()
|
||||
pool.undefine()
|
||||
except Exception:
|
||||
log.debug("Error cleaning up pool", exc_info=True)
|
||||
|
|
|
@ -5,358 +5,331 @@ import tests.utils
|
|||
from . import lib
|
||||
|
||||
|
||||
class Manager(lib.testcase.UITestCase):
|
||||
#############################################################
|
||||
# UI tests for manager window, and basic VM lifecycle stuff #
|
||||
#############################################################
|
||||
|
||||
def _testVMLifecycle(app):
|
||||
"""
|
||||
UI tests for manager window, and basic VM lifecycle stuff
|
||||
Basic VM lifecycle test, shared between standard and no-events
|
||||
testing
|
||||
"""
|
||||
manager = app.topwin
|
||||
shutdown = manager.find("Shut Down", "push button")
|
||||
pause = manager.find("Pause", "toggle button")
|
||||
run = manager.find("Run", "push button")
|
||||
force = manager.find("Force Off", "menu item")
|
||||
smenu = manager.find("Menu", "toggle button")
|
||||
save = manager.find("Save", "menu item")
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
c = manager.find("test-many-devices", "table cell")
|
||||
c.click()
|
||||
smenu.click()
|
||||
force.click()
|
||||
app.click_alert_button("Are you sure you want", "Yes")
|
||||
lib.utils.check(lambda: run.sensitive, timeout=5)
|
||||
|
||||
def _testVMLifecycle(self):
|
||||
"""
|
||||
Basic VM lifecycle test, shared between standard and no-events
|
||||
testing
|
||||
"""
|
||||
manager = self.app.topwin
|
||||
shutdown = manager.find("Shut Down", "push button")
|
||||
pause = manager.find("Pause", "toggle button")
|
||||
run = manager.find("Run", "push button")
|
||||
force = manager.find("Force Off", "menu item")
|
||||
smenu = manager.find("Menu", "toggle button")
|
||||
save = manager.find("Save", "menu item")
|
||||
|
||||
c = manager.find("test-many-devices", "table cell")
|
||||
c.click()
|
||||
smenu.click()
|
||||
force.click()
|
||||
self.app.click_alert_button("Are you sure you want", "Yes")
|
||||
lib.utils.check(lambda: run.sensitive, timeout=5)
|
||||
|
||||
run.click()
|
||||
lib.utils.check(lambda: not run.sensitive, timeout=5)
|
||||
pause.click()
|
||||
lib.utils.check(lambda: pause.checked, timeout=5)
|
||||
pause.click()
|
||||
lib.utils.check(lambda: not pause.checked, timeout=5)
|
||||
smenu.click()
|
||||
save.click()
|
||||
lib.utils.check(lambda: run.sensitive, timeout=5)
|
||||
lib.utils.check(lambda: "Saved" in c.text)
|
||||
run.click()
|
||||
lib.utils.check(lambda: shutdown.sensitive, timeout=5)
|
||||
|
||||
def testVMLifecycle(self):
|
||||
# qemu hits some different domain code paths for setTime
|
||||
self.app.uri = tests.utils.URIs.kvm
|
||||
self._testVMLifecycle()
|
||||
|
||||
def testVMNoEventsLifecycle(self):
|
||||
self.app.open(extra_opts=["--test-options=no-events"])
|
||||
|
||||
# Change preferences timeout to 1 second
|
||||
self.app.root.find("Edit", "menu").click()
|
||||
self.app.root.find("Preferences", "menu item").click()
|
||||
win = self.app.root.find_fuzzy("Preferences", "frame")
|
||||
win.find("Polling", "page tab").click()
|
||||
win.find("cpu-poll").set_text("1")
|
||||
win.find("Close", "push button").click()
|
||||
|
||||
self._testVMLifecycle()
|
||||
|
||||
def testVMLifecycleExtra(self):
|
||||
"""
|
||||
Test vmmenu lifecycle options
|
||||
"""
|
||||
self.app.open(keyfile="confirm-all.ini")
|
||||
manager = self.app.topwin
|
||||
run = manager.find("Run", "push button")
|
||||
shutdown = manager.find("Shut Down", "push button")
|
||||
pause = manager.find("Pause", "toggle button")
|
||||
|
||||
def confirm_is_running():
|
||||
lib.utils.check(lambda: not run.sensitive)
|
||||
|
||||
def confirm_is_shutdown():
|
||||
lib.utils.check(lambda: not shutdown.sensitive)
|
||||
|
||||
def confirm_is_paused():
|
||||
lib.utils.check(lambda: pause.checked)
|
||||
|
||||
def confirm_not_paused():
|
||||
lib.utils.check(lambda: not pause.checked)
|
||||
|
||||
def test_action(action, shutdown=True, confirm=True):
|
||||
def _select():
|
||||
cell = manager.find("test\n", "table cell")
|
||||
cell.click(button=3)
|
||||
menu = self.app.root.find("vm-action-menu")
|
||||
menu.check_onscreen()
|
||||
if shutdown:
|
||||
smenu = menu.find("Shut Down", "menu")
|
||||
smenu.point()
|
||||
smenu.check_onscreen()
|
||||
item = smenu.find(action, "menu item")
|
||||
else:
|
||||
item = menu.find(action, "menu item")
|
||||
item.check_onscreen()
|
||||
item.point()
|
||||
self.app.sleep(.3)
|
||||
item.click()
|
||||
|
||||
_select()
|
||||
if confirm:
|
||||
self.app.click_alert_button("Are you sure", "No")
|
||||
_select()
|
||||
self.app.click_alert_button("Are you sure", "Yes")
|
||||
run.click()
|
||||
lib.utils.check(lambda: not run.sensitive, timeout=5)
|
||||
pause.click()
|
||||
lib.utils.check(lambda: pause.checked, timeout=5)
|
||||
pause.click()
|
||||
lib.utils.check(lambda: not pause.checked, timeout=5)
|
||||
smenu.click()
|
||||
save.click()
|
||||
lib.utils.check(lambda: run.sensitive, timeout=5)
|
||||
lib.utils.check(lambda: "Saved" in c.text)
|
||||
run.click()
|
||||
lib.utils.check(lambda: shutdown.sensitive, timeout=5)
|
||||
|
||||
|
||||
test_action("Force Reset")
|
||||
confirm_is_running()
|
||||
test_action("Reboot")
|
||||
confirm_is_running()
|
||||
test_action("Shut Down")
|
||||
confirm_is_shutdown()
|
||||
test_action("Run", shutdown=False, confirm=False)
|
||||
confirm_is_running()
|
||||
test_action("Force Off")
|
||||
confirm_is_shutdown()
|
||||
test_action("Run", shutdown=False, confirm=False)
|
||||
confirm_is_running()
|
||||
test_action("Pause", shutdown=False)
|
||||
confirm_is_paused()
|
||||
test_action("Resume", shutdown=False, confirm=False)
|
||||
confirm_not_paused()
|
||||
test_action("Save")
|
||||
confirm_is_shutdown()
|
||||
test_action("Restore", shutdown=False, confirm=False)
|
||||
confirm_is_running()
|
||||
def testVMLifecycle(app):
|
||||
# qemu hits some different domain code paths for setTime
|
||||
app.uri = tests.utils.URIs.kvm
|
||||
_testVMLifecycle(app)
|
||||
|
||||
def testManagerSaveCancelError(self):
|
||||
"""
|
||||
Test managed save special behavior
|
||||
"""
|
||||
self.app.open(extra_opts=["--test-options=test-managed-save"])
|
||||
|
||||
manager = self.app.topwin
|
||||
run = manager.find("Run", "push button")
|
||||
smenu = manager.find("Menu", "toggle button")
|
||||
save = manager.find("Save", "menu item")
|
||||
def testVMNoEventsLifecycle(app):
|
||||
app.open(extra_opts=["--test-options=no-events"])
|
||||
|
||||
c = manager.find("test-many-devices", "table cell")
|
||||
c.click()
|
||||
# Change preferences timeout to 1 second
|
||||
app.root.find("Edit", "menu").click()
|
||||
app.root.find("Preferences", "menu item").click()
|
||||
win = app.find_window("Preferences")
|
||||
win.find("Polling", "page tab").click()
|
||||
win.find("cpu-poll").set_text("1")
|
||||
win.find("Close", "push button").click()
|
||||
|
||||
# Save it, attempt a cancel operation
|
||||
smenu.click()
|
||||
save.click()
|
||||
progwin = self.app.root.find("Saving Virtual Machine", "frame")
|
||||
# Attempt cancel which will fail, then find the error message
|
||||
progwin.find("Cancel", "push button").click()
|
||||
progwin.find("Error cancelling save job")
|
||||
lib.utils.check(lambda: not progwin.showing, timeout=5)
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
_testVMLifecycle(app)
|
||||
|
||||
# Restore will fail and offer to remove managed save
|
||||
run.click()
|
||||
self.app.click_alert_button("remove the saved state", "No")
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
run.click()
|
||||
self.app.click_alert_button("remove the saved state", "Yes")
|
||||
|
||||
def testVMLifecycleExtra(app):
|
||||
"""
|
||||
Test vmmenu lifecycle options
|
||||
"""
|
||||
app.open(keyfile="confirm-all.ini")
|
||||
manager = app.topwin
|
||||
run = manager.find("Run", "push button")
|
||||
shutdown = manager.find("Shut Down", "push button")
|
||||
pause = manager.find("Pause", "toggle button")
|
||||
|
||||
def confirm_is_running():
|
||||
lib.utils.check(lambda: not run.sensitive)
|
||||
|
||||
def testManagerQEMUSetTime(self):
|
||||
def confirm_is_shutdown():
|
||||
lib.utils.check(lambda: not shutdown.sensitive)
|
||||
|
||||
def confirm_is_paused():
|
||||
lib.utils.check(lambda: pause.checked)
|
||||
|
||||
def confirm_not_paused():
|
||||
lib.utils.check(lambda: not pause.checked)
|
||||
|
||||
def test_action(**kwargs):
|
||||
app.manager_vm_action("test", confirm_click_no=True, **kwargs)
|
||||
|
||||
confirm_is_running()
|
||||
test_action(reset=True)
|
||||
confirm_is_running()
|
||||
test_action(reboot=True)
|
||||
confirm_is_running()
|
||||
test_action(shutdown=True)
|
||||
confirm_is_shutdown()
|
||||
test_action(run=True)
|
||||
confirm_is_running()
|
||||
test_action(destroy=True)
|
||||
confirm_is_shutdown()
|
||||
test_action(run=True)
|
||||
confirm_is_running()
|
||||
test_action(pause=True)
|
||||
confirm_is_paused()
|
||||
test_action(resume=True)
|
||||
confirm_not_paused()
|
||||
test_action(save=True)
|
||||
confirm_is_shutdown()
|
||||
test_action(restore=True)
|
||||
confirm_is_running()
|
||||
|
||||
|
||||
def testManagerSaveCancelError(app):
|
||||
"""
|
||||
Test managed save special behavior
|
||||
"""
|
||||
app.open(extra_opts=["--test-options=test-managed-save"])
|
||||
|
||||
manager = app.topwin
|
||||
run = manager.find("Run", "push button")
|
||||
smenu = manager.find("Menu", "toggle button")
|
||||
save = manager.find("Save", "menu item")
|
||||
|
||||
c = manager.find("test-many-devices", "table cell")
|
||||
c.click()
|
||||
|
||||
# Save it, attempt a cancel operation
|
||||
smenu.click()
|
||||
save.click()
|
||||
progwin = app.find_window("Saving Virtual Machine")
|
||||
# Attempt cancel which will fail, then find the error message
|
||||
progwin.find("Cancel", "push button").click()
|
||||
progwin.find("Error cancelling save job")
|
||||
lib.utils.check(lambda: not progwin.showing, timeout=5)
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
|
||||
# Restore will fail and offer to remove managed save
|
||||
run.click()
|
||||
app.click_alert_button("remove the saved state", "No")
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
run.click()
|
||||
app.click_alert_button("remove the saved state", "Yes")
|
||||
lib.utils.check(lambda: not run.sensitive)
|
||||
|
||||
|
||||
def testManagerQEMUSetTime(app):
|
||||
"""
|
||||
Fake qemu setTime behavior for code coverage
|
||||
"""
|
||||
app.uri = tests.utils.URIs.kvm
|
||||
manager = app.topwin
|
||||
run = manager.find("Run", "push button")
|
||||
smenu = manager.find("Menu", "toggle button")
|
||||
save = manager.find("Save", "menu item")
|
||||
|
||||
c = manager.find("test alternate devs title", "table cell")
|
||||
c.click()
|
||||
|
||||
# Save -> resume -> save
|
||||
smenu.click()
|
||||
save.click()
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
app.sleep(1)
|
||||
run.click()
|
||||
lib.utils.check(lambda: not run.sensitive)
|
||||
app.sleep(1)
|
||||
smenu.click()
|
||||
save.click()
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
app.sleep(1)
|
||||
|
||||
|
||||
def testManagerVMRunFail(app):
|
||||
# Force VM startup to fail so we can test the error path
|
||||
app.open(extra_opts=["--test-options=test-vm-run-fail"])
|
||||
|
||||
manager = app.topwin
|
||||
|
||||
c = manager.find("test-clone-simple", "table cell")
|
||||
c.click()
|
||||
manager.find("Run", "push button").click()
|
||||
app.click_alert_button("fake error", "Close")
|
||||
|
||||
|
||||
|
||||
def testManagerColumns(app):
|
||||
# Enable all stat options
|
||||
# Need to expand the window size so all columns are onscreen
|
||||
app.open(keyfile="winsize.ini")
|
||||
app.root.find("Edit", "menu").click()
|
||||
app.root.find("Preferences", "menu item").click()
|
||||
win = app.find_window("Preferences")
|
||||
win.find("Polling", "page tab").click()
|
||||
win.find_fuzzy("Poll Disk", "check").click()
|
||||
win.find_fuzzy("Poll Network", "check").click()
|
||||
win.find_fuzzy("Poll Memory", "check").click()
|
||||
win.find("Close", "push button").click()
|
||||
|
||||
manager = app.topwin
|
||||
def _test_sort(name):
|
||||
col = manager.find(name, "table column header")
|
||||
col.check_onscreen()
|
||||
# Trigger sorting
|
||||
col.click()
|
||||
col.click()
|
||||
|
||||
def _click_column_menu(name):
|
||||
manager.find("View", "menu").click()
|
||||
menu = manager.find("Graph", "menu")
|
||||
menu.point()
|
||||
menu.find_fuzzy(name, "check menu item").click()
|
||||
|
||||
def _test_column(name):
|
||||
_click_column_menu(name)
|
||||
_test_sort(name)
|
||||
|
||||
_test_sort("Name")
|
||||
_click_column_menu("Guest CPU")
|
||||
_click_column_menu("Guest CPU")
|
||||
_test_sort("CPU usage")
|
||||
_test_column("Host CPU")
|
||||
_test_column("Memory")
|
||||
_test_column("Disk I/O")
|
||||
_test_column("Network I/O")
|
||||
|
||||
|
||||
def testManagerWindowReposition(app):
|
||||
"""
|
||||
Restore previous position when window is reopened
|
||||
"""
|
||||
manager = app.topwin
|
||||
host = app.manager_open_host("Storage")
|
||||
fmenu = host.find("File", "menu")
|
||||
fmenu.click()
|
||||
fmenu.find("View Manager", "menu item").click()
|
||||
lib.utils.check(lambda: manager.active)
|
||||
|
||||
manager.window_maximize()
|
||||
newx = manager.position[0]
|
||||
newy = manager.position[1]
|
||||
manager.keyCombo("<alt>F4")
|
||||
host.click_title()
|
||||
host.find("File", "menu").click()
|
||||
host.find("View Manager", "menu item").click()
|
||||
lib.utils.check(lambda: manager.showing)
|
||||
assert manager.position == (newx, newy)
|
||||
|
||||
|
||||
|
||||
def testManagerWindowCleanup(app):
|
||||
"""
|
||||
Open migrate, clone, delete, newvm, details, host windows, close the
|
||||
connection, make sure they all disappear
|
||||
"""
|
||||
def _drag(win):
|
||||
"""
|
||||
Fake qemu setTime behavior for code coverage
|
||||
Drag a window so it's not obscuring the manager window
|
||||
"""
|
||||
self.app.uri = tests.utils.URIs.kvm
|
||||
manager = self.app.topwin
|
||||
run = manager.find("Run", "push button")
|
||||
smenu = manager.find("Menu", "toggle button")
|
||||
save = manager.find("Save", "menu item")
|
||||
win.drag(1000, 1000)
|
||||
|
||||
c = manager.find("test alternate devs title", "table cell")
|
||||
c.click()
|
||||
manager = app.topwin
|
||||
app.sleep(1)
|
||||
manager.window_maximize()
|
||||
|
||||
# Save -> resume -> save
|
||||
smenu.click()
|
||||
save.click()
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
self.app.sleep(1)
|
||||
run.click()
|
||||
lib.utils.check(lambda: not run.sensitive)
|
||||
self.app.sleep(1)
|
||||
smenu.click()
|
||||
save.click()
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
self.app.sleep(1)
|
||||
# Open delete window hitting a special code path, then close it
|
||||
manager.find("test-many-devices", "table cell").click()
|
||||
manager.find("Edit", "menu").click()
|
||||
manager.find("Delete", "menu item").click()
|
||||
delete = app.root.find_fuzzy("Delete", "frame")
|
||||
app.sleep(.5)
|
||||
delete.click_title()
|
||||
delete.window_close()
|
||||
|
||||
def testManagerVMRunFail(self):
|
||||
# Force VM startup to fail so we can test the error path
|
||||
self.app.open(extra_opts=["--test-options=test-vm-run-fail"])
|
||||
# Open Clone window hitting a special code path, then close it
|
||||
manager.find("test-clone", "table cell").click()
|
||||
app.rawinput.pressKey("Menu")
|
||||
app.root.find("Clone...", "menu item").click()
|
||||
clone = app.find_window("Clone Virtual Machine")
|
||||
app.sleep(.5)
|
||||
clone.click_title()
|
||||
clone.window_close()
|
||||
|
||||
manager = self.app.topwin
|
||||
# Open host
|
||||
c = manager.find_fuzzy("testdriver.xml", "table cell")
|
||||
c.click()
|
||||
app.sleep(.5)
|
||||
c.doubleClick()
|
||||
host = app.find_window("test testdriver.xml - Connection Details")
|
||||
_drag(host)
|
||||
|
||||
c = manager.find("test-clone-simple", "table cell")
|
||||
c.click()
|
||||
manager.find("Run", "push button").click()
|
||||
self.app.click_alert_button("fake error", "Close")
|
||||
# Open details
|
||||
c = manager.find("test-many-devices", "table cell")
|
||||
c.click()
|
||||
app.sleep(.5)
|
||||
c.doubleClick()
|
||||
details = app.find_details_window("test-many-devices")
|
||||
_drag(details)
|
||||
|
||||
# Close the connection
|
||||
app.sleep(.5)
|
||||
manager.click_title()
|
||||
app.sleep(.5)
|
||||
app.manager_conn_disconnect("test testdriver.xml")
|
||||
|
||||
# Ensure all those windows aren't showing
|
||||
lib.utils.check(lambda: not details.showing)
|
||||
|
||||
# Delete the connection, ensure the host dialog disappears
|
||||
app.manager_conn_delete("test testdriver.xml")
|
||||
lib.utils.check(lambda: not host.showing)
|
||||
|
||||
|
||||
def testManagerColumns(self):
|
||||
# Enable all stat options
|
||||
# Need to expand the window size so all columns are onscreen
|
||||
self.app.open(keyfile="winsize.ini")
|
||||
self.app.root.find("Edit", "menu").click()
|
||||
self.app.root.find("Preferences", "menu item").click()
|
||||
win = self.app.root.find_fuzzy("Preferences", "frame")
|
||||
win.find("Polling", "page tab").click()
|
||||
win.find_fuzzy("Poll Disk", "check").click()
|
||||
win.find_fuzzy("Poll Network", "check").click()
|
||||
win.find_fuzzy("Poll Memory", "check").click()
|
||||
win.find("Close", "push button").click()
|
||||
def testManagerDefaultStartup(app):
|
||||
app.open(use_uri=False)
|
||||
manager = app.topwin
|
||||
errlabel = manager.find("error-label")
|
||||
lib.utils.check(
|
||||
lambda: "Checking for virtualization" in errlabel.text)
|
||||
lib.utils.check(
|
||||
lambda: "File->Add Connection" in errlabel.text)
|
||||
lib.utils.check(
|
||||
lambda: "appropriate QEMU/KVM" in errlabel.text)
|
||||
|
||||
manager = self.app.topwin
|
||||
def _test_sort(name):
|
||||
col = manager.find(name, "table column header")
|
||||
col.check_onscreen()
|
||||
# Trigger sorting
|
||||
col.click()
|
||||
col.click()
|
||||
|
||||
def _click_column_menu(name):
|
||||
manager.find("View", "menu").click()
|
||||
menu = manager.find("Graph", "menu")
|
||||
menu.point()
|
||||
menu.find_fuzzy(name, "check menu item").click()
|
||||
|
||||
def _test_column(name):
|
||||
_click_column_menu(name)
|
||||
_test_sort(name)
|
||||
|
||||
_test_sort("Name")
|
||||
_click_column_menu("Guest CPU")
|
||||
_click_column_menu("Guest CPU")
|
||||
_test_sort("CPU usage")
|
||||
_test_column("Host CPU")
|
||||
_test_column("Memory")
|
||||
_test_column("Disk I/O")
|
||||
_test_column("Network I/O")
|
||||
|
||||
def testManagerWindowReposition(self):
|
||||
"""
|
||||
Restore previous position when window is reopened
|
||||
"""
|
||||
manager = self.app.topwin
|
||||
host = self.app.open_host_window("Storage")
|
||||
fmenu = host.find("File", "menu")
|
||||
fmenu.click()
|
||||
fmenu.find("View Manager", "menu item").click()
|
||||
lib.utils.check(lambda: manager.active)
|
||||
|
||||
# Double click title to maximize
|
||||
manager.click_title()
|
||||
manager.click_title()
|
||||
newx = manager.position[0]
|
||||
newy = manager.position[1]
|
||||
manager.keyCombo("<alt>F4")
|
||||
host.click_title()
|
||||
host.find("File", "menu").click()
|
||||
host.find("View Manager", "menu item").click()
|
||||
lib.utils.check(lambda: manager.showing)
|
||||
assert manager.position == (newx, newy)
|
||||
manager.find("File", "menu").click()
|
||||
manager.find("Quit", "menu item").click()
|
||||
|
||||
|
||||
def testManagerWindowCleanup(self):
|
||||
"""
|
||||
Open migrate, clone, delete, newvm, details, host windows, close the
|
||||
connection, make sure they all disappear
|
||||
"""
|
||||
def _drag(win):
|
||||
"""
|
||||
Drag a window so it's not obscuring the manager window
|
||||
"""
|
||||
win.drag(1000, 1000)
|
||||
|
||||
manager = self.app.topwin
|
||||
|
||||
# Open migrate dialog
|
||||
c = manager.find("test-many-devices", "table cell")
|
||||
c.click(button=3)
|
||||
self.app.root.find("Migrate...", "menu item").click()
|
||||
migrate = self.app.root.find("Migrate the virtual machine", "frame")
|
||||
_drag(migrate)
|
||||
|
||||
# Open clone dialog
|
||||
c = manager.find("test-clone", "table cell")
|
||||
c.click()
|
||||
self.app.rawinput.pressKey("Menu")
|
||||
self.app.root.find("Clone...", "menu item").click()
|
||||
clone = self.app.root.find("Clone Virtual Machine", "frame")
|
||||
_drag(clone)
|
||||
|
||||
# Open delete dialog
|
||||
c.click()
|
||||
manager.find("Edit", "menu").click()
|
||||
manager.find("Delete", "menu item").click()
|
||||
delete = self.app.root.find_fuzzy("Delete", "frame")
|
||||
_drag(delete)
|
||||
|
||||
# Open NewVM
|
||||
self.app.root.find("New", "push button").click()
|
||||
create = self.app.root.find("New VM", "frame")
|
||||
_drag(create)
|
||||
|
||||
# Open host
|
||||
c = manager.find_fuzzy("testdriver.xml", "table cell")
|
||||
c.doubleClick()
|
||||
host = self.app.root.find_fuzzy("Connection Details", "frame")
|
||||
_drag(host)
|
||||
|
||||
# Open details
|
||||
details = self.app.open_details_window("test-many-devices")
|
||||
_drag(details)
|
||||
|
||||
# Close the connection
|
||||
self.app.sleep(1)
|
||||
manager.click()
|
||||
c = manager.find_fuzzy("testdriver.xml", "table cell")
|
||||
c.click()
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-disconnect", "menu item").click()
|
||||
|
||||
# Ensure all those windows aren't showing
|
||||
lib.utils.check(lambda: not migrate.showing)
|
||||
lib.utils.check(lambda: not clone.showing)
|
||||
lib.utils.check(lambda: not create.showing)
|
||||
lib.utils.check(lambda: not details.showing)
|
||||
lib.utils.check(lambda: not delete.showing)
|
||||
|
||||
# Delete the connection, ensure the host dialog disappears
|
||||
c = manager.find_fuzzy("testdriver.xml", "table cell")
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-delete", "menu item").click()
|
||||
self.app.click_alert_button("will remove the connection", "Yes")
|
||||
lib.utils.check(lambda: not host.showing)
|
||||
|
||||
def testManagerDefaultStartup(self):
|
||||
self.app.open(use_uri=False)
|
||||
manager = self.app.topwin
|
||||
errlabel = manager.find("error-label")
|
||||
lib.utils.check(
|
||||
lambda: "Checking for virtualization" in errlabel.text)
|
||||
lib.utils.check(
|
||||
lambda: "File->Add Connection" in errlabel.text)
|
||||
lib.utils.check(
|
||||
lambda: "appropriate QEMU/KVM" in errlabel.text)
|
||||
|
||||
manager.find("File", "menu").click()
|
||||
manager.find("Quit", "menu item").click()
|
||||
|
||||
def testManagerConnOpenFail(self):
|
||||
self.app.open(keyfile="baduri.ini")
|
||||
manager = self.app.topwin
|
||||
manager.find_fuzzy("bad uri", "table cell").doubleClick()
|
||||
lib.utils.check(lambda: not manager.active)
|
||||
self.app.click_alert_button("Unable to connect", "Close")
|
||||
lib.utils.check(lambda: manager.active)
|
||||
def testManagerConnOpenFail(app):
|
||||
app.open(keyfile="baduri.ini")
|
||||
manager = app.topwin
|
||||
manager.find_fuzzy("bad uri", "table cell").doubleClick()
|
||||
lib.utils.check(lambda: not manager.active)
|
||||
app.click_alert_button("Unable to connect", "Close")
|
||||
lib.utils.check(lambda: manager.active)
|
||||
|
|
|
@ -4,100 +4,101 @@
|
|||
from . import lib
|
||||
|
||||
|
||||
class MediaChange(lib.testcase.UITestCase):
|
||||
#############################################
|
||||
# UI tests for details storage media change #
|
||||
#############################################
|
||||
|
||||
def testMediaChange(app):
|
||||
vmname = "test-many-devices"
|
||||
app.open(show_console=vmname)
|
||||
win = app.find_details_window(vmname,
|
||||
click_details=True, shutdown=True)
|
||||
hw = win.find("hw-list")
|
||||
tab = win.find("disk-tab")
|
||||
combo = win.find("media-combo")
|
||||
entry = win.find("media-entry")
|
||||
appl = win.find("config-apply")
|
||||
|
||||
# Floppy + physical
|
||||
hw.find("Floppy 1", "table cell").click()
|
||||
combo.click_combo_entry()
|
||||
combo.find(r"Floppy_install_label \(/dev/fdb\)")
|
||||
lib.utils.check(lambda: entry.text == "No media detected (/dev/fda)")
|
||||
entry.click()
|
||||
entry.click_secondary_icon()
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
|
||||
# Enter /dev/fdb, after apply it should change to pretty label
|
||||
entry.set_text("/dev/fdb")
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda:
|
||||
entry.text == "Floppy_install_label (/dev/fdb)")
|
||||
|
||||
# Specify manual path
|
||||
path = "/tmp/aaaaaaaaaaaaaaaaaaaaaaa.img"
|
||||
entry.set_text(path)
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: entry.text == path)
|
||||
|
||||
# Go to Floppy 2, make sure previous path is in recent list
|
||||
hw.find("Floppy 2", "table cell").click()
|
||||
combo.click_combo_entry()
|
||||
combo.find(path)
|
||||
entry.click()
|
||||
# Use the storage browser to select new floppy storage
|
||||
tab.find("Browse", "push button").click()
|
||||
app.select_storagebrowser_volume("default-pool", "iso-vol")
|
||||
appl.click()
|
||||
|
||||
# Browse for image
|
||||
hw.find("IDE CDROM 1", "table cell").click()
|
||||
combo.click_combo_entry()
|
||||
combo.find(r"Fedora12_media \(/dev/sr0\)")
|
||||
entry.click()
|
||||
tab.find("Browse", "push button").click()
|
||||
app.select_storagebrowser_volume("default-pool", "backingl1.img")
|
||||
# Check 'already in use' dialog
|
||||
appl.click()
|
||||
app.click_alert_button("already in use by", "No")
|
||||
lib.utils.check(lambda: appl.sensitive)
|
||||
appl.click()
|
||||
app.click_alert_button("already in use by", "Yes")
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: "backing" in entry.text)
|
||||
entry.set_text("")
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
|
||||
|
||||
|
||||
def testMediaHotplug(app):
|
||||
"""
|
||||
UI tests for details storage media change
|
||||
Test in the case of a running VM
|
||||
"""
|
||||
vmname = "test-many-devices"
|
||||
app.open(show_console=vmname)
|
||||
win = app.find_details_window(vmname, click_details=True)
|
||||
hw = win.find("hw-list")
|
||||
entry = win.find("media-entry")
|
||||
appl = win.find("config-apply")
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
# CDROM + physical
|
||||
hw.find("IDE CDROM 1", "table cell").click()
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
entry.set_text("/dev/sr0")
|
||||
appl.click()
|
||||
app.click_alert_button("changes will take effect", "OK")
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
|
||||
def testMediaChange(self):
|
||||
win = self.app.open_details_window("test-many-devices", shutdown=True)
|
||||
hw = win.find("hw-list")
|
||||
tab = win.find("disk-tab")
|
||||
combo = win.find("media-combo")
|
||||
entry = win.find("media-entry")
|
||||
appl = win.find("config-apply")
|
||||
|
||||
# Floppy + physical
|
||||
hw.find("Floppy 1", "table cell").click()
|
||||
combo.click_combo_entry()
|
||||
combo.find(r"Floppy_install_label \(/dev/fdb\)")
|
||||
lib.utils.check(lambda: entry.text == "No media detected (/dev/fda)")
|
||||
entry.click()
|
||||
entry.click_secondary_icon()
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
|
||||
# Enter /dev/fdb, after apply it should change to pretty label
|
||||
entry.set_text("/dev/fdb")
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda:
|
||||
entry.text == "Floppy_install_label (/dev/fdb)")
|
||||
|
||||
# Specify manual path
|
||||
path = "/tmp/aaaaaaaaaaaaaaaaaaaaaaa.img"
|
||||
entry.set_text(path)
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: entry.text == path)
|
||||
|
||||
# Go to Floppy 2, make sure previous path is in recent list
|
||||
hw.find("Floppy 2", "table cell").click()
|
||||
combo.click_combo_entry()
|
||||
combo.find(path)
|
||||
entry.click()
|
||||
# Use the storage browser to select new floppy storage
|
||||
tab.find("Browse", "push button").click()
|
||||
self.app.select_storagebrowser_volume("default-pool", "iso-vol")
|
||||
appl.click()
|
||||
|
||||
# Browse for image
|
||||
hw.find("IDE CDROM 1", "table cell").click()
|
||||
combo.click_combo_entry()
|
||||
combo.find(r"Fedora12_media \(/dev/sr0\)")
|
||||
entry.click()
|
||||
tab.find("Browse", "push button").click()
|
||||
self.app.select_storagebrowser_volume("default-pool", "backingl1.img")
|
||||
# Check 'already in use' dialog
|
||||
appl.click()
|
||||
self.app.click_alert_button("already in use by", "No")
|
||||
lib.utils.check(lambda: appl.sensitive)
|
||||
appl.click()
|
||||
self.app.click_alert_button("already in use by", "Yes")
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: "backing" in entry.text)
|
||||
entry.set_text("")
|
||||
appl.click()
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
|
||||
|
||||
def testMediaHotplug(self):
|
||||
"""
|
||||
Test in the case of a running VM
|
||||
"""
|
||||
win = self.app.open_details_window("test-many-devices")
|
||||
hw = win.find("hw-list")
|
||||
entry = win.find("media-entry")
|
||||
appl = win.find("config-apply")
|
||||
|
||||
# CDROM + physical
|
||||
hw.find("IDE CDROM 1", "table cell").click()
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
entry.set_text("/dev/sr0")
|
||||
appl.click()
|
||||
self.app.click_alert_button("changes will take effect", "OK")
|
||||
lib.utils.check(lambda: not appl.sensitive)
|
||||
lib.utils.check(lambda: not entry.text)
|
||||
|
||||
# Shutdown the VM, verify change shows up
|
||||
win.find("Shut Down", "push button").click()
|
||||
run = win.find("Run", "push button")
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
lib.utils.check(lambda: entry.text == "Fedora12_media (/dev/sr0)")
|
||||
# Shutdown the VM, verify change shows up
|
||||
win.find("Shut Down", "push button").click()
|
||||
run = win.find("Run", "push button")
|
||||
lib.utils.check(lambda: run.sensitive)
|
||||
lib.utils.check(lambda: entry.text == "Fedora12_media (/dev/sr0)")
|
||||
|
|
|
@ -5,149 +5,147 @@ import tests.utils
|
|||
from . import lib
|
||||
|
||||
|
||||
class VMMMigrate(lib.testcase.UITestCase):
|
||||
###################################
|
||||
# UI tests for the migrate dialog #
|
||||
###################################
|
||||
|
||||
def _open_migrate(app, vmname):
|
||||
app.manager_vm_action(vmname, migrate=True)
|
||||
return app.find_window("Migrate the virtual machine")
|
||||
|
||||
|
||||
def testMigrateQemu(app):
|
||||
# Use fake qemu connections
|
||||
app.uri = tests.utils.URIs.kvm
|
||||
newuri = (tests.utils.URIs.test_default +
|
||||
",fakeuri=qemu+tcp://fakehost/system")
|
||||
app.manager_createconn(newuri)
|
||||
|
||||
# Run default migrate
|
||||
mig = _open_migrate(app, "test-many-devices")
|
||||
mig.find("Migrate", "push button").click()
|
||||
app.click_alert_button(
|
||||
"the.connection.driver:.virDomainMigrate", "Close")
|
||||
mig.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
|
||||
# Run with deselected URI
|
||||
mig = _open_migrate(app, "test-many-devices")
|
||||
mig.find("address-check").click()
|
||||
label = mig.find("Let libvirt decide")
|
||||
label.check_onscreen()
|
||||
mig.find("Migrate", "push button").click()
|
||||
app.click_alert_button(
|
||||
"the.connection.driver:.virDomainMigrate", "Close")
|
||||
mig.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
|
||||
# Run with tunnelled and other options
|
||||
mig = _open_migrate(app, "test-many-devices")
|
||||
mig.combo_select("Mode:", "Tunnelled")
|
||||
mig.find("Advanced", "toggle button").click_expander()
|
||||
mig.find("Allow unsafe:", "check box").click()
|
||||
mig.find("Temporary", "check box").click()
|
||||
|
||||
mig.find("Migrate", "push button").click()
|
||||
app.click_alert_button("p2p migration", "Close")
|
||||
mig.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
|
||||
|
||||
def testMigrateXen(app):
|
||||
# Use fake xen connections
|
||||
app.uri = tests.utils.URIs.test_full + ",fakeuri=xen:///"
|
||||
|
||||
fakeremotexen = (tests.utils.URIs.test_default +
|
||||
",fakeuri=xen+tcp://fakehost/")
|
||||
app.manager_createconn(fakeremotexen)
|
||||
|
||||
# Run default migrate
|
||||
mig = _open_migrate(app, "test-many-devices")
|
||||
mig.find("Migrate", "push button").click()
|
||||
app.click_alert_button(
|
||||
"the.connection.driver:.virDomainMigrate", "Close")
|
||||
mig.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
|
||||
|
||||
def testMigrateMock(app):
|
||||
"""
|
||||
UI tests for the migrate dialog
|
||||
Trigger the mock migration testing we have to emulate success
|
||||
"""
|
||||
# Add an additional connection
|
||||
app.manager_createconn("test:///default")
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
# Run it and check some values
|
||||
mig = _open_migrate(app, "test-many-devices")
|
||||
mig.find("address-text").set_text("TESTSUITE-FAKE")
|
||||
|
||||
def _add_conn(self, uri):
|
||||
manager = self.app.root
|
||||
manager.find("File", "menu").click()
|
||||
manager.find("Add Connection...", "menu item").click()
|
||||
win = manager.find_fuzzy("Add Connection", "dialog")
|
||||
win.combo_select("Hypervisor", "Custom URI")
|
||||
win.find("uri-entry", "text").set_text(uri)
|
||||
win.find("Connect", "push button").click()
|
||||
lib.utils.check(lambda: win.showing is False)
|
||||
mig.find("Migrate", "push button").click()
|
||||
progwin = app.find_window("Migrating VM")
|
||||
# Attempt cancel which will fail, then find the error message
|
||||
progwin.find("Cancel", "push button").click()
|
||||
progwin.find("Error cancelling migrate job")
|
||||
lib.utils.check(lambda: not progwin.showing, timeout=5)
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
|
||||
def _open_migrate(self, vmname):
|
||||
c = self.app.root.find(vmname, "table cell")
|
||||
c.click(button=3)
|
||||
self.app.root.find("Migrate...", "menu item").click()
|
||||
return self.app.root.find("Migrate the virtual machine", "frame")
|
||||
|
||||
def testMigrateQemu(self):
|
||||
# Use fake qemu connections
|
||||
self.app.uri = tests.utils.URIs.kvm
|
||||
self._add_conn(tests.utils.URIs.test_default +
|
||||
",fakeuri=qemu+tcp://fakehost/system")
|
||||
def testMigrateConnMismatch(app):
|
||||
# Add a possible target but disconnect it
|
||||
app.uri = tests.utils.URIs.test_default
|
||||
manager = app.topwin
|
||||
manager.window_maximize()
|
||||
manager.click()
|
||||
app.manager_conn_disconnect("test default")
|
||||
|
||||
# Run default migrate
|
||||
mig = self._open_migrate("test-many-devices")
|
||||
mig.find("Migrate", "push button").click()
|
||||
self.app.click_alert_button(
|
||||
"the.connection.driver:.virDomainMigrate", "Close")
|
||||
mig.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
# Add a mismatched hv connection
|
||||
fakexen = tests.utils.URIs.test_empty + ",fakeuri=xen:///"
|
||||
app.manager_createconn(fakexen)
|
||||
|
||||
# Run with deselected URI
|
||||
mig = self._open_migrate("test-many-devices")
|
||||
mig.find("address-check").click()
|
||||
label = mig.find("Let libvirt decide")
|
||||
label.check_onscreen()
|
||||
mig.find("Migrate", "push button").click()
|
||||
self.app.click_alert_button(
|
||||
"the.connection.driver:.virDomainMigrate", "Close")
|
||||
mig.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
# Open dialog and confirm no conns are available
|
||||
app.manager_createconn(tests.utils.URIs.test_full)
|
||||
mig = _open_migrate(app, "test-many-devices")
|
||||
mig.find("conn-combo").find("No usable", "menu item")
|
||||
|
||||
# Run with tunnelled and other options
|
||||
mig = self._open_migrate("test-many-devices")
|
||||
mig.combo_select("Mode:", "Tunnelled")
|
||||
mig.find("Advanced", "toggle button").click_expander()
|
||||
mig.find("Allow unsafe:", "check box").click()
|
||||
mig.find("Temporary", "check box").click()
|
||||
# Test explicit dialog 'delete'
|
||||
mig.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
|
||||
mig.find("Migrate", "push button").click()
|
||||
self.app.click_alert_button("p2p migration", "Close")
|
||||
mig.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
# Ensure disconnecting will close the dialog
|
||||
manager.click_title()
|
||||
mig = _open_migrate(app, "test-many-devices")
|
||||
app.manager_conn_disconnect("test testdriver.xml")
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
|
||||
def testMigrateXen(self):
|
||||
# Use fake xen connections
|
||||
self.app.uri = tests.utils.URIs.test_full + ",fakeuri=xen:///"
|
||||
|
||||
fakeremotexen = (tests.utils.URIs.test_default +
|
||||
",fakeuri=xen+tcp://fakehost/")
|
||||
self._add_conn(fakeremotexen)
|
||||
def testMigrateXMLEditor(app):
|
||||
app.open(xmleditor_enabled=True)
|
||||
manager = app.topwin
|
||||
|
||||
# Run default migrate
|
||||
mig = self._open_migrate("test-many-devices")
|
||||
mig.find("Migrate", "push button").click()
|
||||
self.app.click_alert_button(
|
||||
"the.connection.driver:.virDomainMigrate", "Close")
|
||||
mig.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
# Add an additional connection
|
||||
app.manager_createconn("test:///default")
|
||||
|
||||
def testMigrateMock(self):
|
||||
"""
|
||||
Trigger the mock migration testing we have to emulate success
|
||||
"""
|
||||
# Add an additional connection
|
||||
self._add_conn("test:///default")
|
||||
# Run it and check some values
|
||||
vmname = "test-many-devices"
|
||||
win = _open_migrate(app, vmname)
|
||||
win.find("address-text").set_text("TESTSUITE-FAKE")
|
||||
|
||||
# Run it and check some values
|
||||
mig = self._open_migrate("test-many-devices")
|
||||
mig.find("address-text").set_text("TESTSUITE-FAKE")
|
||||
# Create a new obj with XML edited name, verify it worked
|
||||
newname = "aafroofroo"
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
newtext = xmleditor.text.replace(
|
||||
">%s<" % vmname, ">%s<" % newname)
|
||||
xmleditor.set_text(newtext)
|
||||
win.find("Migrate", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing, timeout=10)
|
||||
|
||||
mig.find("Migrate", "push button").click()
|
||||
progwin = self.app.root.find("Migrating VM", "frame")
|
||||
# Attempt cancel which will fail, then find the error message
|
||||
progwin.find("Cancel", "push button").click()
|
||||
progwin.find("Error cancelling migrate job")
|
||||
lib.utils.check(lambda: not progwin.showing, timeout=5)
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
manager.find(newname, "table cell")
|
||||
|
||||
def testMigrateConnMismatch(self):
|
||||
# Add a possible target but disconnect it
|
||||
self.app.uri = tests.utils.URIs.test_default
|
||||
c = self.app.root.find("test default", "table cell")
|
||||
c.click(button=3)
|
||||
self.app.root.find("conn-disconnect", "menu item").click()
|
||||
|
||||
# Add a mismatched hv connection
|
||||
fakexen = tests.utils.URIs.test_empty + ",fakeuri=xen:///"
|
||||
self._add_conn(fakexen)
|
||||
|
||||
# Open dialog and confirm no conns are available
|
||||
self._add_conn(tests.utils.URIs.test_full)
|
||||
mig = self._open_migrate("test-many-devices")
|
||||
mig.find("conn-combo").find("No usable", "menu item")
|
||||
mig.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: not mig.showing)
|
||||
|
||||
def testMigrateXMLEditor(self):
|
||||
self.app.open(xmleditor_enabled=True)
|
||||
manager = self.app.topwin
|
||||
|
||||
# Add an additional connection
|
||||
self._add_conn("test:///default")
|
||||
|
||||
# Run it and check some values
|
||||
vmname = "test-many-devices"
|
||||
win = self._open_migrate(vmname)
|
||||
win.find("address-text").set_text("TESTSUITE-FAKE")
|
||||
|
||||
# Create a new obj with XML edited name, verify it worked
|
||||
newname = "aafroofroo"
|
||||
win.find("XML", "page tab").click()
|
||||
xmleditor = win.find("XML editor")
|
||||
newtext = xmleditor.text.replace(
|
||||
">%s<" % vmname, ">%s<" % newname)
|
||||
xmleditor.set_text(newtext)
|
||||
win.find("Migrate", "push button").click()
|
||||
lib.utils.check(lambda: not win.showing, timeout=10)
|
||||
|
||||
manager.find(newname, "table cell")
|
||||
|
||||
# Do standard xmleditor tests
|
||||
win = self._open_migrate(vmname)
|
||||
win.find("address-text").set_text("TESTSUITE-FAKE")
|
||||
finish = win.find("Migrate", "push button")
|
||||
lib.utils.test_xmleditor_interactions(self.app, win, finish)
|
||||
win.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.visible)
|
||||
# Do standard xmleditor tests
|
||||
win = _open_migrate(app, vmname)
|
||||
win.find("address-text").set_text("TESTSUITE-FAKE")
|
||||
finish = win.find("Migrate", "push button")
|
||||
lib.utils.test_xmleditor_interactions(app, win, finish)
|
||||
win.find("Cancel", "push button").click()
|
||||
lib.utils.check(lambda: not win.visible)
|
||||
|
|
|
@ -4,137 +4,134 @@
|
|||
from . import lib
|
||||
|
||||
|
||||
class VMMPrefs(lib.testcase.UITestCase):
|
||||
#######################################
|
||||
# UI tests for the preferences dialog #
|
||||
#######################################
|
||||
|
||||
def testPrefsAll(app):
|
||||
app.root.find("Edit", "menu").click()
|
||||
app.root.find("Preferences", "menu item").click()
|
||||
|
||||
win = app.find_window("Preferences")
|
||||
generaltab = win.find("general-tab")
|
||||
pollingtab = win.find("polling-tab")
|
||||
newvmtab = win.find("newvm-tab")
|
||||
consoletab = win.find("console-tab")
|
||||
feedbacktab = win.find("feedback-tab")
|
||||
|
||||
feedbacktab.check_not_onscreen()
|
||||
tab = generaltab
|
||||
tab.check_onscreen()
|
||||
tab.find_fuzzy("Enable system tray", "check").click()
|
||||
tab.find_fuzzy("Enable XML").click()
|
||||
tab.find_fuzzy("libguestfs VM").click()
|
||||
|
||||
win.find("Polling", "page tab").click()
|
||||
tab = pollingtab
|
||||
tab.check_onscreen()
|
||||
tab.find("Poll CPU", "check box").click()
|
||||
tab.find("Poll Disk", "check box").click()
|
||||
tab.find("Poll Memory", "check box").click()
|
||||
tab.find("Poll Network", "check box").click()
|
||||
period = tab.find_fuzzy("cpu-poll", "spin button")
|
||||
period.click()
|
||||
period.set_text("5")
|
||||
|
||||
win.find("New VM", "page tab").click()
|
||||
tab = newvmtab
|
||||
tab.check_onscreen()
|
||||
tab.find("Add sound device", "check box").click()
|
||||
tab.combo_select("CPU default:", "Copy host")
|
||||
tab.combo_select("Storage format:", "Raw")
|
||||
tab.combo_select("prefs-add-spice-usbredir", "No")
|
||||
tab.combo_select("Graphics type", "VNC")
|
||||
|
||||
win.find("Console", "page tab").click()
|
||||
tab = consoletab
|
||||
tab.check_onscreen()
|
||||
tab.combo_select("SPICE USB", "Manual redirect")
|
||||
tab.combo_select("Resize guest", "On")
|
||||
tab.combo_select("Graphical console scaling", "Always")
|
||||
tab.find("Console autoconnect", "check box").click()
|
||||
|
||||
tab.find("Change...", "push button").click()
|
||||
keyframe = app.find_window("Configure grab")
|
||||
|
||||
# On certain environments pressing "Alt_L" and
|
||||
# clicking a window starts window drag operation.
|
||||
# Work around by pushing both Control and Alt.
|
||||
app.rawinput.holdKey("Control_L")
|
||||
app.rawinput.holdKey("Alt_L")
|
||||
app.rawinput.holdKey("Z")
|
||||
|
||||
# Test releasekey handler
|
||||
app.rawinput.releaseKey("Z")
|
||||
app.rawinput.holdKey("Z")
|
||||
try:
|
||||
keyframe.find_fuzzy("OK", "push button").click()
|
||||
finally:
|
||||
app.rawinput.releaseKey("Z")
|
||||
app.rawinput.releaseKey("Alt_L")
|
||||
app.rawinput.releaseKey("Control_L")
|
||||
|
||||
win.find("Feedback", "page tab").click()
|
||||
tab = feedbacktab
|
||||
tab.check_onscreen()
|
||||
tab.find("Force Poweroff", "check box").click()
|
||||
tab.find("Poweroff/Reboot", "check box").click()
|
||||
tab.find("Pause", "check box").click()
|
||||
tab.find("Device removal", "check box").click()
|
||||
tab.find("Unapplied changes", "check box").click()
|
||||
tab.find("Deleting storage", "check box").click()
|
||||
|
||||
win.find("General", "page tab").click()
|
||||
win.find_fuzzy("Enable system tray", "check").click()
|
||||
|
||||
win.find_fuzzy("Close", "push button").click()
|
||||
lib.utils.check(lambda: win.visible is False)
|
||||
|
||||
|
||||
|
||||
def testPrefsXMLEditor(app):
|
||||
managerwin = app.topwin
|
||||
managerwin.drag(0, 200)
|
||||
detailswin = app.manager_open_details("test-clone-simple")
|
||||
finish = detailswin.find("config-apply")
|
||||
xmleditor = detailswin.find("XML editor")
|
||||
|
||||
detailswin.find("XML", "page tab").click()
|
||||
warnlabel = detailswin.find_fuzzy("XML editing is disabled")
|
||||
lib.utils.check(lambda: warnlabel.visible)
|
||||
origtext = xmleditor.text
|
||||
xmleditor.typeText("1234abcd")
|
||||
lib.utils.check(lambda: xmleditor.text == origtext)
|
||||
|
||||
managerwin.click_title()
|
||||
managerwin.grabFocus()
|
||||
managerwin.find("Edit", "menu").click()
|
||||
managerwin.find("Preferences", "menu item").click()
|
||||
prefswin = app.find_window("Preferences")
|
||||
prefswin.find_fuzzy("Enable XML").click()
|
||||
prefswin.find_fuzzy("Close", "push button").click()
|
||||
lib.utils.check(lambda: prefswin.visible is False)
|
||||
|
||||
managerwin.keyCombo("<alt>F4")
|
||||
detailswin.click()
|
||||
newtext = xmleditor.text.replace(">", "><title>FOOTITLE</title>", 1)
|
||||
xmleditor.set_text(newtext)
|
||||
finish.click()
|
||||
detailswin.find("Details", "page tab").click()
|
||||
lib.utils.check(lambda:
|
||||
detailswin.find("Title:", "text").text == "FOOTITLE")
|
||||
|
||||
|
||||
def testPrefsKeyfile(app):
|
||||
"""
|
||||
UI tests for the preferences dialog
|
||||
Preload some keyfile settings and verify they work as expected
|
||||
"""
|
||||
app.open(use_uri=False, keyfile="defaultconn.ini")
|
||||
managerwin = app.topwin
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
|
||||
def testPrefsAll(self):
|
||||
self.app.root.find("Edit", "menu").click()
|
||||
self.app.root.find("Preferences", "menu item").click()
|
||||
|
||||
win = self.app.root.find_fuzzy("Preferences", "frame")
|
||||
generaltab = win.find("general-tab")
|
||||
pollingtab = win.find("polling-tab")
|
||||
newvmtab = win.find("newvm-tab")
|
||||
consoletab = win.find("console-tab")
|
||||
feedbacktab = win.find("feedback-tab")
|
||||
|
||||
feedbacktab.check_not_onscreen()
|
||||
tab = generaltab
|
||||
tab.check_onscreen()
|
||||
tab.find_fuzzy("Enable system tray", "check").click()
|
||||
tab.find_fuzzy("Enable XML").click()
|
||||
tab.find_fuzzy("libguestfs VM").click()
|
||||
|
||||
win.find("Polling", "page tab").click()
|
||||
tab = pollingtab
|
||||
tab.check_onscreen()
|
||||
tab.find("Poll CPU", "check box").click()
|
||||
tab.find("Poll Disk", "check box").click()
|
||||
tab.find("Poll Memory", "check box").click()
|
||||
tab.find("Poll Network", "check box").click()
|
||||
period = tab.find_fuzzy("cpu-poll", "spin button")
|
||||
period.click()
|
||||
period.set_text("5")
|
||||
|
||||
win.find("New VM", "page tab").click()
|
||||
tab = newvmtab
|
||||
tab.check_onscreen()
|
||||
tab.find("Add sound device", "check box").click()
|
||||
tab.combo_select("CPU default:", "Copy host")
|
||||
tab.combo_select("Storage format:", "Raw")
|
||||
tab.combo_select("prefs-add-spice-usbredir", "No")
|
||||
tab.combo_select("Graphics type", "VNC")
|
||||
|
||||
win.find("Console", "page tab").click()
|
||||
tab = consoletab
|
||||
tab.check_onscreen()
|
||||
tab.combo_select("SPICE USB", "Manual redirect")
|
||||
tab.combo_select("Resize guest", "On")
|
||||
tab.combo_select("Graphical console scaling", "Always")
|
||||
tab.find("Console autoconnect", "check box").click()
|
||||
|
||||
tab.find("Change...", "push button").click()
|
||||
keyframe = self.app.root.find_fuzzy("Configure grab", "dialog")
|
||||
|
||||
# On certain environments pressing "Alt_L" and
|
||||
# clicking a window starts window drag operation.
|
||||
# Work around by pushing both Control and Alt.
|
||||
self.app.rawinput.holdKey("Control_L")
|
||||
self.app.rawinput.holdKey("Alt_L")
|
||||
self.app.rawinput.holdKey("Z")
|
||||
|
||||
# Test releasekey handler
|
||||
self.app.rawinput.releaseKey("Z")
|
||||
self.app.rawinput.holdKey("Z")
|
||||
try:
|
||||
keyframe.find_fuzzy("OK", "push button").click()
|
||||
finally:
|
||||
self.app.rawinput.releaseKey("Z")
|
||||
self.app.rawinput.releaseKey("Alt_L")
|
||||
self.app.rawinput.releaseKey("Control_L")
|
||||
|
||||
win.find("Feedback", "page tab").click()
|
||||
tab = feedbacktab
|
||||
tab.check_onscreen()
|
||||
tab.find("Force Poweroff", "check box").click()
|
||||
tab.find("Poweroff/Reboot", "check box").click()
|
||||
tab.find("Pause", "check box").click()
|
||||
tab.find("Device removal", "check box").click()
|
||||
tab.find("Unapplied changes", "check box").click()
|
||||
tab.find("Deleting storage", "check box").click()
|
||||
|
||||
win.find("General", "page tab").click()
|
||||
win.find_fuzzy("Enable system tray", "check").click()
|
||||
|
||||
win.find_fuzzy("Close", "push button").click()
|
||||
lib.utils.check(lambda: win.visible is False)
|
||||
|
||||
|
||||
def testPrefsXMLEditor(self):
|
||||
managerwin = self.app.topwin
|
||||
managerwin.drag(0, 200)
|
||||
detailswin = self.app.open_details_window("test-clone-simple")
|
||||
finish = detailswin.find("config-apply")
|
||||
xmleditor = detailswin.find("XML editor")
|
||||
|
||||
detailswin.find("XML", "page tab").click()
|
||||
warnlabel = detailswin.find_fuzzy("XML editing is disabled")
|
||||
lib.utils.check(lambda: warnlabel.visible)
|
||||
origtext = xmleditor.text
|
||||
xmleditor.typeText("1234abcd")
|
||||
lib.utils.check(lambda: xmleditor.text == origtext)
|
||||
|
||||
managerwin.click_title()
|
||||
managerwin.grabFocus()
|
||||
managerwin.find("Edit", "menu").click()
|
||||
managerwin.find("Preferences", "menu item").click()
|
||||
prefswin = self.app.root.find_fuzzy("Preferences", "frame")
|
||||
prefswin.find_fuzzy("Enable XML").click()
|
||||
prefswin.find_fuzzy("Close", "push button").click()
|
||||
lib.utils.check(lambda: prefswin.visible is False)
|
||||
|
||||
managerwin.keyCombo("<alt>F4")
|
||||
detailswin.click()
|
||||
newtext = xmleditor.text.replace(">", "><title>FOOTITLE</title>", 1)
|
||||
xmleditor.set_text(newtext)
|
||||
finish.click()
|
||||
detailswin.find("Details", "page tab").click()
|
||||
lib.utils.check(lambda:
|
||||
detailswin.find("Title:", "text").text == "FOOTITLE")
|
||||
|
||||
def testPrefsKeyfile(self):
|
||||
"""
|
||||
Preload some keyfile settings and verify they work as expected
|
||||
"""
|
||||
self.app.open(use_uri=False, keyfile="defaultconn.ini")
|
||||
managerwin = self.app.topwin
|
||||
|
||||
# test:///default should be connected
|
||||
managerwin.find("test default", "table cell")
|
||||
managerwin.find("foo - Not Connected", "table cell")
|
||||
# test:///default should be connected
|
||||
managerwin.find("test default", "table cell")
|
||||
managerwin.find("foo - Not Connected", "table cell")
|
||||
|
|
|
@ -4,189 +4,177 @@
|
|||
from . import lib
|
||||
|
||||
|
||||
class Snapshots(lib.testcase.UITestCase):
|
||||
############################################
|
||||
# UI tests for virt-manager's VM snapshots #
|
||||
############################################
|
||||
|
||||
_DEFAULT_VMNAME = "test-snapshots"
|
||||
|
||||
|
||||
def _open_snapshots_window(app, vmname=_DEFAULT_VMNAME):
|
||||
if not app.is_running():
|
||||
app.open(show_console=vmname)
|
||||
win = app.find_details_window(vmname)
|
||||
win.find("Snapshots", "radio button").click()
|
||||
return win
|
||||
|
||||
|
||||
def testSnapshotsSmokeTest(app):
|
||||
"""
|
||||
UI tests for virt-manager's VM snapshots
|
||||
Smoke test to ensure all snapshots show correctly
|
||||
"""
|
||||
|
||||
###################
|
||||
# Private helpers #
|
||||
###################
|
||||
|
||||
def _open_snapshots_window(self, vmname="test-snapshots"):
|
||||
self.app.root.find_fuzzy(vmname, "table cell").click(button=3)
|
||||
self.app.root.find("Open", "menu item").click()
|
||||
|
||||
win = self.app.root.find("%s on" % vmname, "frame")
|
||||
win.find("Snapshots", "radio button").click()
|
||||
return win
|
||||
win = _open_snapshots_window(app)
|
||||
errlabel = win.find("snapshot-error-label", "label")
|
||||
lst = win.find("snapshot-list", "table")
|
||||
lib.utils.walkUIList(app, win, lst, lambda: errlabel.showing)
|
||||
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
def testSnapshotLifecycle(app):
|
||||
"""
|
||||
Create/delete/start/stop snapshots
|
||||
"""
|
||||
win = _open_snapshots_window(app)
|
||||
vmrun = win.find("Run", "push button")
|
||||
vmpause = win.find("Pause", "toggle button")
|
||||
snaprun = win.find("snapshot-start", "push button")
|
||||
|
||||
def testSnapshotsSmokeTest(self):
|
||||
"""
|
||||
Smoke test to ensure all snapshots show correctly
|
||||
"""
|
||||
win = self._open_snapshots_window()
|
||||
errlabel = win.find("snapshot-error-label", "label")
|
||||
lst = win.find("snapshot-list", "table")
|
||||
lib.utils.walkUIList(self.app, win, lst, lambda: errlabel.showing)
|
||||
# Start already running snapshot
|
||||
snapname = "internal-root"
|
||||
win.find(snapname, "table cell").click()
|
||||
snaprun.click()
|
||||
app.click_alert_button("run the snapshot '%s'" % snapname, "Yes")
|
||||
lib.utils.check(lambda: not vmrun.sensitive)
|
||||
|
||||
def testSnapshotLifecycle(self):
|
||||
"""
|
||||
Create/delete/start/stop snapshots
|
||||
"""
|
||||
win = self._open_snapshots_window()
|
||||
vmrun = win.find("Run", "push button")
|
||||
vmpause = win.find("Pause", "toggle button")
|
||||
snaprun = win.find("snapshot-start", "push button")
|
||||
# Start offline snapshot
|
||||
snapname = "offline-root"
|
||||
win.find(snapname, "table cell").click()
|
||||
snaprun.click()
|
||||
app.click_alert_button("run the snapshot '%s'" % snapname, "No")
|
||||
lib.utils.check(lambda: not vmrun.sensitive)
|
||||
snaprun.click()
|
||||
app.click_alert_button("run the snapshot '%s'" % snapname, "Yes")
|
||||
lib.utils.check(lambda: vmrun.sensitive)
|
||||
|
||||
# Start already running snapshot
|
||||
snapname = "internal-root"
|
||||
win.find(snapname, "table cell").click()
|
||||
snaprun.click()
|
||||
self.app.click_alert_button("run the snapshot '%s'" % snapname, "Yes")
|
||||
lib.utils.check(lambda: not vmrun.sensitive)
|
||||
# Start paused snapshot
|
||||
snapname = "snap-paused"
|
||||
win.find(snapname, "table cell").click()
|
||||
snaprun.click()
|
||||
app.click_alert_button("run the snapshot '%s'" % snapname, "Yes")
|
||||
lib.utils.check(lambda: vmpause.checked)
|
||||
|
||||
# Start offline snapshot
|
||||
snapname = "offline-root"
|
||||
win.find(snapname, "table cell").click()
|
||||
snaprun.click()
|
||||
self.app.click_alert_button("run the snapshot '%s'" % snapname, "No")
|
||||
lib.utils.check(lambda: not vmrun.sensitive)
|
||||
snaprun.click()
|
||||
self.app.click_alert_button("run the snapshot '%s'" % snapname, "Yes")
|
||||
lib.utils.check(lambda: vmrun.sensitive)
|
||||
# Edit snapshot
|
||||
descui = win.find("snapshot-description")
|
||||
desc = "TESTSNAP"
|
||||
descui.set_text(desc)
|
||||
win.find("snapshot-apply", "push button").click()
|
||||
win.find("snapshot-refresh", "push button").click()
|
||||
lib.utils.check(lambda: descui.text == desc)
|
||||
# Apply by clicking away
|
||||
desc += " ROUND2"
|
||||
descui.set_text(desc)
|
||||
win.find("internal-root", "table cell").click()
|
||||
app.click_alert_button("There are unapplied changes", "Yes")
|
||||
|
||||
# Start paused snapshot
|
||||
snapname = "snap-paused"
|
||||
win.find(snapname, "table cell").click()
|
||||
snaprun.click()
|
||||
self.app.click_alert_button("run the snapshot '%s'" % snapname, "Yes")
|
||||
lib.utils.check(lambda: vmpause.checked)
|
||||
# Create new snapshot
|
||||
win.find("snapshot-add", "push button").click()
|
||||
newwin = app.find_window("Create snapshot")
|
||||
snapname = "testnewsnap"
|
||||
newwin.find("Name:", "text").set_text(snapname)
|
||||
newwin.find("Description:", "text").set_text("testdesc")
|
||||
newwin.find("Finish", "push button").click()
|
||||
lib.utils.check(lambda: not newwin.showing)
|
||||
newc = win.find(snapname, "table cell")
|
||||
lib.utils.check(lambda: newc.state_selected)
|
||||
|
||||
# Edit snapshot
|
||||
descui = win.find("snapshot-description")
|
||||
desc = "TESTSNAP"
|
||||
descui.set_text(desc)
|
||||
win.find("snapshot-apply", "push button").click()
|
||||
win.find("snapshot-refresh", "push button").click()
|
||||
lib.utils.check(lambda: descui.text == desc)
|
||||
# Apply by clicking away
|
||||
desc += " ROUND2"
|
||||
descui.set_text(desc)
|
||||
win.find("internal-root", "table cell").click()
|
||||
self.app.click_alert_button("There are unapplied changes", "Yes")
|
||||
# Delete it
|
||||
win.find("snapshot-delete", "push button").click()
|
||||
app.click_alert_button("permanently delete", "No")
|
||||
lib.utils.check(lambda: not newc.dead)
|
||||
win.find("snapshot-delete", "push button").click()
|
||||
app.click_alert_button("permanently delete", "Yes")
|
||||
lib.utils.check(lambda: newc.dead)
|
||||
|
||||
# Create new snapshot
|
||||
win.find("snapshot-add", "push button").click()
|
||||
newwin = self.app.root.find("Create snapshot", "frame")
|
||||
snapname = "testnewsnap"
|
||||
newwin.find("Name:", "text").set_text(snapname)
|
||||
newwin.find("Description:", "text").set_text("testdesc")
|
||||
newwin.find("Finish", "push button").click()
|
||||
lib.utils.check(lambda: not newwin.showing)
|
||||
newc = win.find(snapname, "table cell")
|
||||
lib.utils.check(lambda: newc.state_selected)
|
||||
# Recreate another snapshot with the same name
|
||||
win.find("snapshot-add", "push button").click()
|
||||
newwin = app.find_window("Create snapshot")
|
||||
snapname = "testnewsnap"
|
||||
newwin.find("Name:", "text").set_text(snapname)
|
||||
newwin.find("Finish", "push button").click()
|
||||
lib.utils.check(lambda: not newwin.showing)
|
||||
newc = win.find(snapname, "table cell")
|
||||
lib.utils.check(lambda: newc.state_selected)
|
||||
|
||||
# Delete it
|
||||
win.find("snapshot-delete", "push button").click()
|
||||
self.app.click_alert_button("permanently delete", "No")
|
||||
lib.utils.check(lambda: not newc.dead)
|
||||
win.find("snapshot-delete", "push button").click()
|
||||
self.app.click_alert_button("permanently delete", "Yes")
|
||||
lib.utils.check(lambda: newc.dead)
|
||||
# Switch out of window
|
||||
win.find("Details", "radio button").click()
|
||||
lib.utils.check(lambda: not snaprun.showing)
|
||||
|
||||
# Recreate another snapshot with the same name
|
||||
win.find("snapshot-add", "push button").click()
|
||||
newwin = self.app.root.find("Create snapshot", "frame")
|
||||
snapname = "testnewsnap"
|
||||
newwin.find("Name:", "text").set_text(snapname)
|
||||
newwin.find("Finish", "push button").click()
|
||||
lib.utils.check(lambda: not newwin.showing)
|
||||
newc = win.find(snapname, "table cell")
|
||||
lib.utils.check(lambda: newc.state_selected)
|
||||
|
||||
# Switch out of window
|
||||
win.find("Details", "radio button").click()
|
||||
lib.utils.check(lambda: not snaprun.showing)
|
||||
def testSnapshotMisc1(app):
|
||||
"""
|
||||
Test snapshot corner cases
|
||||
"""
|
||||
vmname = "test-state-managedsave"
|
||||
win = _open_snapshots_window(app, vmname)
|
||||
vmrun = win.find("Restore", "push button")
|
||||
|
||||
def testSnapshotMisc1(self):
|
||||
"""
|
||||
Test snapshot corner cases
|
||||
"""
|
||||
manager = self.app.topwin
|
||||
manager.find("vm-list").click()
|
||||
for ignore in range(8):
|
||||
self.app.rawinput.pressKey("Down")
|
||||
vmname = "test-state-managedsave"
|
||||
cell = manager.find_fuzzy(vmname, "table cell")
|
||||
cell.bring_on_screen()
|
||||
# Create new snapshot
|
||||
win.find("snapshot-add", "push button").click()
|
||||
app.click_alert_button("not become part of the snapshot", "Cancel")
|
||||
lib.utils.check(lambda: win.active)
|
||||
win.find("snapshot-add", "push button").click()
|
||||
app.click_alert_button("not become part of the snapshot", "OK")
|
||||
newwin = app.find_window("Create snapshot")
|
||||
snapname1 = "testnewsnap1"
|
||||
newwin.find("Name:", "text").set_text(snapname1)
|
||||
newwin.find("Finish", "push button").click()
|
||||
lib.utils.check(lambda: not newwin.showing)
|
||||
newc = win.find(snapname1, "table cell")
|
||||
lib.utils.check(lambda: newc.state_selected)
|
||||
|
||||
win = self._open_snapshots_window(vmname=vmname)
|
||||
vmrun = win.find("Restore", "push button")
|
||||
# Start the VM, create another snapshot
|
||||
vmrun.click()
|
||||
lib.utils.check(lambda: not vmrun.sensitive)
|
||||
win.find("snapshot-add", "push button").click()
|
||||
newwin = app.find_window("Create snapshot")
|
||||
# Force validation error
|
||||
newwin.find("Name:", "text").set_text("bad name")
|
||||
newwin.find("Finish", "push button").click()
|
||||
app.click_alert_button("validating snapshot", "OK")
|
||||
# Force name collision
|
||||
newwin.find("Name:", "text").set_text(snapname1)
|
||||
newwin.find("Finish", "push button").click()
|
||||
app.click_alert_button(snapname1, "Close")
|
||||
# Make it succeed
|
||||
snapname2 = "testnewsnap2"
|
||||
newwin.find("Name:", "text").set_text(snapname2)
|
||||
newwin.find("Finish", "push button").click()
|
||||
lib.utils.check(lambda: not newwin.showing)
|
||||
newc = win.find(snapname2, "table cell")
|
||||
lib.utils.check(lambda: newc.state_selected)
|
||||
|
||||
# Create new snapshot
|
||||
win.find("snapshot-add", "push button").click()
|
||||
self.app.click_alert_button("not become part of the snapshot", "Cancel")
|
||||
lib.utils.check(lambda: win.active)
|
||||
win.find("snapshot-add", "push button").click()
|
||||
self.app.click_alert_button("not become part of the snapshot", "OK")
|
||||
newwin = self.app.root.find("Create snapshot", "frame")
|
||||
snapname1 = "testnewsnap1"
|
||||
newwin.find("Name:", "text").set_text(snapname1)
|
||||
newwin.find("Finish", "push button").click()
|
||||
lib.utils.check(lambda: not newwin.showing)
|
||||
newc = win.find(snapname1, "table cell")
|
||||
lib.utils.check(lambda: newc.state_selected)
|
||||
# Trigger another managed save warning
|
||||
smenu = win.find("Menu", "toggle button")
|
||||
smenu.click()
|
||||
save = smenu.find("Save", "menu item")
|
||||
save.click()
|
||||
lib.utils.check(lambda: vmrun.sensitive)
|
||||
win.find(snapname1, "table cell").click(button=3)
|
||||
app.root.find("Start snapshot", "menu item").click()
|
||||
app.click_alert_button("run the snapshot '%s'" % snapname1, "Yes")
|
||||
app.click_alert_button("no memory state", "Cancel")
|
||||
win.find("snapshot-start").click()
|
||||
app.click_alert_button("run the snapshot '%s'" % snapname1, "Yes")
|
||||
app.click_alert_button("no memory state", "OK")
|
||||
|
||||
# Start the VM, create another snapshot
|
||||
vmrun.click()
|
||||
lib.utils.check(lambda: not vmrun.sensitive)
|
||||
win.find("snapshot-add", "push button").click()
|
||||
newwin = self.app.root.find("Create snapshot", "frame")
|
||||
# Force validation error
|
||||
newwin.find("Name:", "text").set_text("bad name")
|
||||
newwin.find("Finish", "push button").click()
|
||||
self.app.click_alert_button("validating snapshot", "OK")
|
||||
# Force name collision
|
||||
newwin.find("Name:", "text").set_text(snapname1)
|
||||
newwin.find("Finish", "push button").click()
|
||||
self.app.click_alert_button(snapname1, "Close")
|
||||
# Make it succeed
|
||||
snapname2 = "testnewsnap2"
|
||||
newwin.find("Name:", "text").set_text(snapname2)
|
||||
newwin.find("Finish", "push button").click()
|
||||
lib.utils.check(lambda: not newwin.showing)
|
||||
newc = win.find(snapname2, "table cell")
|
||||
lib.utils.check(lambda: newc.state_selected)
|
||||
|
||||
# Trigger another managed save warning
|
||||
smenu = win.find("Menu", "toggle button")
|
||||
smenu.click()
|
||||
save = smenu.find("Save", "menu item")
|
||||
save.click()
|
||||
lib.utils.check(lambda: vmrun.sensitive)
|
||||
win.find(snapname1, "table cell").click(button=3)
|
||||
self.app.root.find("Start snapshot", "menu item").click()
|
||||
self.app.click_alert_button("run the snapshot '%s'" % snapname1, "Yes")
|
||||
self.app.click_alert_button("no memory state", "Cancel")
|
||||
win.find("snapshot-start").click()
|
||||
self.app.click_alert_button("run the snapshot '%s'" % snapname1, "Yes")
|
||||
self.app.click_alert_button("no memory state", "OK")
|
||||
|
||||
# Multi select
|
||||
cell1 = win.find(snapname1, "table cell")
|
||||
cell2 = win.find(snapname2, "table cell")
|
||||
cell1.click()
|
||||
self.app.rawinput.holdKey("Shift_L")
|
||||
self.app.rawinput.pressKey("Down")
|
||||
self.app.rawinput.releaseKey("Shift_L")
|
||||
win.find("snapshot-delete").click()
|
||||
self.app.click_alert_button("permanently delete", "Yes")
|
||||
lib.utils.check(lambda: cell1.dead)
|
||||
lib.utils.check(lambda: cell2.dead)
|
||||
lib.utils.check(lambda: win.active)
|
||||
# Multi select
|
||||
cell1 = win.find(snapname1, "table cell")
|
||||
cell2 = win.find(snapname2, "table cell")
|
||||
cell1.click()
|
||||
app.rawinput.holdKey("Shift_L")
|
||||
app.rawinput.pressKey("Down")
|
||||
app.rawinput.releaseKey("Shift_L")
|
||||
win.find("snapshot-delete").click()
|
||||
app.click_alert_button("permanently delete", "Yes")
|
||||
lib.utils.check(lambda: cell1.dead)
|
||||
lib.utils.check(lambda: cell2.dead)
|
||||
lib.utils.check(lambda: win.active)
|
||||
|
|
|
@ -5,120 +5,113 @@ import tests.utils
|
|||
from . import lib
|
||||
|
||||
|
||||
class Systray(lib.testcase.UITestCase):
|
||||
"""
|
||||
UI tests for virt-manager's systray using a fake testing backend
|
||||
"""
|
||||
####################################################################
|
||||
# UI tests for virt-manager's systray using a fake testing backend #
|
||||
####################################################################
|
||||
|
||||
##############
|
||||
# Test cases #
|
||||
##############
|
||||
def testSystrayFake(app):
|
||||
app.open(
|
||||
keyfile="systray.ini",
|
||||
extra_opts=["--test-options=fake-systray"],
|
||||
window_name="Virtual Machine Manager")
|
||||
|
||||
def testSystrayFake(self):
|
||||
self.app.open(
|
||||
keyfile="systray.ini",
|
||||
extra_opts=["--test-options=fake-systray"],
|
||||
window_name="Virtual Machine Manager")
|
||||
manager = app.topwin
|
||||
systray = app.root.find("vmm-fake-systray", check_active=False)
|
||||
manager.drag(1000, 1000)
|
||||
|
||||
manager = self.app.topwin
|
||||
systray = self.app.root.find("vmm-fake-systray", check_active=False)
|
||||
manager.drag(1000, 1000)
|
||||
# Add a connection to trigger systray update
|
||||
uri = tests.utils.URIs.kvm
|
||||
app.manager_createconn(uri=uri)
|
||||
|
||||
# Add a connection to trigger systray update
|
||||
uri = tests.utils.URIs.kvm
|
||||
manager.find("File", "menu").click()
|
||||
manager.find("Add Connection...", "menu item").click()
|
||||
win = self.app.root.find_fuzzy("Add Connection", "dialog")
|
||||
win.combo_select("Hypervisor", "Custom URI")
|
||||
win.find("uri-entry", "text").set_text(uri)
|
||||
win.find("Connect", "push button").click()
|
||||
# Hide the manager
|
||||
systray.click_title()
|
||||
systray.click()
|
||||
lib.utils.check(lambda: not manager.showing)
|
||||
lib.utils.check(lambda: app.is_running())
|
||||
|
||||
# Hide the manager
|
||||
systray.click_title()
|
||||
systray.click()
|
||||
lib.utils.check(lambda: not manager.showing)
|
||||
lib.utils.check(lambda: self.app.is_running())
|
||||
systray.click(button=3)
|
||||
menu = app.root.find("vmm-systray-menu")
|
||||
|
||||
systray.click(button=3)
|
||||
menu = self.app.root.find("vmm-systray-menu")
|
||||
|
||||
def _get_conn_action(connstr, actionstr):
|
||||
if not menu.showing:
|
||||
systray.click(button=3)
|
||||
lib.utils.check(lambda: menu.showing)
|
||||
connmenu = menu.find(connstr, "menu")
|
||||
connmenu.point()
|
||||
return connmenu.find(actionstr, "menu")
|
||||
|
||||
def _check_conn_action(connstr, actionstr):
|
||||
item = _get_conn_action(connstr, actionstr)
|
||||
lib.utils.check(lambda: item.showing)
|
||||
def _get_conn_action(connstr, actionstr):
|
||||
if not menu.showing:
|
||||
systray.click(button=3)
|
||||
lib.utils.check(lambda: not menu.showing)
|
||||
lib.utils.check(lambda: menu.showing)
|
||||
connmenu = menu.find(connstr, "menu")
|
||||
connmenu.point()
|
||||
ret = connmenu.find(actionstr, "menu")
|
||||
ret.check_onscreen()
|
||||
return ret
|
||||
|
||||
def _do_conn_action(connstr, actionstr):
|
||||
item = _get_conn_action(connstr, actionstr)
|
||||
item.click()
|
||||
lib.utils.check(lambda: not menu.showing)
|
||||
def _check_conn_action(connstr, actionstr):
|
||||
item = _get_conn_action(connstr, actionstr)
|
||||
lib.utils.check(lambda: item.showing)
|
||||
app.rawinput.pressKey("Escape")
|
||||
lib.utils.check(lambda: not menu.showing)
|
||||
|
||||
def _get_vm_action(connstr, vmname, action):
|
||||
vmenu = _get_conn_action(connstr, vmname)
|
||||
vmenu.point()
|
||||
return vmenu.find(action, "menu")
|
||||
def _do_conn_action(connstr, actionstr):
|
||||
item = _get_conn_action(connstr, actionstr)
|
||||
item.click()
|
||||
lib.utils.check(lambda: not menu.showing)
|
||||
|
||||
def _check_vm_action(connstr, vmname, action):
|
||||
item = _get_vm_action(connstr, vmname, action)
|
||||
lib.utils.check(lambda: item.showing)
|
||||
systray.click(button=3)
|
||||
lib.utils.check(lambda: not menu.showing)
|
||||
def _get_vm_action(connstr, vmname, action):
|
||||
vmenu = _get_conn_action(connstr, vmname)
|
||||
vmenu.point()
|
||||
return vmenu.find(action, "menu")
|
||||
|
||||
def _do_vm_action(connstr, vmname, action):
|
||||
item = _get_vm_action(connstr, vmname, action)
|
||||
item.click()
|
||||
lib.utils.check(lambda: not menu.showing)
|
||||
def _check_vm_action(connstr, vmname, action):
|
||||
item = _get_vm_action(connstr, vmname, action)
|
||||
lib.utils.check(lambda: item.showing)
|
||||
app.rawinput.pressKey("Escape")
|
||||
lib.utils.check(lambda: not menu.showing)
|
||||
|
||||
# Right click start a connection
|
||||
_check_conn_action("QEMU/KVM", "Disconnect")
|
||||
_do_conn_action("test default", "Connect")
|
||||
_check_conn_action("test default", "Disconnect")
|
||||
_do_conn_action("test testdriver", "Disconnect")
|
||||
_check_conn_action("test testdriver", "Connect")
|
||||
def _do_vm_action(connstr, vmname, action):
|
||||
item = _get_vm_action(connstr, vmname, action)
|
||||
item.click()
|
||||
lib.utils.check(lambda: not menu.showing)
|
||||
|
||||
# Trigger VM change
|
||||
_do_vm_action("QEMU/KVM", "test-arm-kernel", "Pause")
|
||||
_check_vm_action("QEMU/KVM", "test-arm-kernel", "Resume")
|
||||
# Right click start a connection
|
||||
_check_conn_action("QEMU/KVM", "Disconnect")
|
||||
_do_conn_action("test default", "Connect")
|
||||
_check_conn_action("test default", "Disconnect")
|
||||
_do_conn_action("test testdriver", "Disconnect")
|
||||
_check_conn_action("test testdriver", "Connect")
|
||||
|
||||
# Reshow the manager
|
||||
systray.click()
|
||||
lib.utils.check(lambda: manager.showing)
|
||||
lib.utils.check(lambda: self.app.is_running())
|
||||
# Trigger VM change
|
||||
_do_vm_action("QEMU/KVM", "test-arm-kernel", "Pause")
|
||||
_check_vm_action("QEMU/KVM", "test-arm-kernel", "Resume")
|
||||
|
||||
# Close from the menu
|
||||
systray.click_title()
|
||||
systray.click(button=3)
|
||||
menu = self.app.root.find("vmm-systray-menu")
|
||||
menu.find("Quit", "menu item").click()
|
||||
# Reshow the manager
|
||||
systray.click()
|
||||
lib.utils.check(lambda: manager.showing)
|
||||
lib.utils.check(lambda: app.is_running())
|
||||
|
||||
lib.utils.check(lambda: not self.app.is_running())
|
||||
# Close from the menu
|
||||
systray.click_title()
|
||||
systray.click(button=3)
|
||||
menu = app.root.find("vmm-systray-menu")
|
||||
menu.find("Quit", "menu item").click()
|
||||
|
||||
def testSystrayToggle(self):
|
||||
self.app.open(
|
||||
keyfile="systray.ini",
|
||||
extra_opts=["--test-options=fake-systray"],
|
||||
window_name="Virtual Machine Manager")
|
||||
lib.utils.check(lambda: not app.is_running())
|
||||
|
||||
manager = self.app.topwin
|
||||
systray = self.app.root.find("vmm-fake-systray", check_active=False)
|
||||
manager.find("Edit", "menu").click()
|
||||
manager.find("Preferences", "menu item").click()
|
||||
prefs = self.app.root.find_fuzzy("Preferences", "frame")
|
||||
|
||||
# Close the system tray
|
||||
prefs.click_title()
|
||||
prefs.find_fuzzy("Enable system tray", "check").click()
|
||||
lib.utils.check(lambda: not systray.showing)
|
||||
def testSystrayToggle(app):
|
||||
app.open(
|
||||
keyfile="systray.ini",
|
||||
extra_opts=["--test-options=fake-systray"],
|
||||
window_name="Virtual Machine Manager")
|
||||
|
||||
# Close the manager
|
||||
manager.click_title()
|
||||
manager.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: not self.app.is_running())
|
||||
manager = app.topwin
|
||||
systray = app.root.find("vmm-fake-systray", check_active=False)
|
||||
manager.find("Edit", "menu").click()
|
||||
manager.find("Preferences", "menu item").click()
|
||||
prefs = app.find_window("Preferences")
|
||||
|
||||
# Close the system tray
|
||||
prefs.click_title()
|
||||
prefs.find_fuzzy("Enable system tray", "check").click()
|
||||
lib.utils.check(lambda: not systray.showing)
|
||||
|
||||
# Close the manager
|
||||
manager.click_title()
|
||||
manager.keyCombo("<alt>F4")
|
||||
lib.utils.check(lambda: not app.is_running())
|
||||
|
|
|
@ -1185,7 +1185,7 @@ class vmmConnection(vmmGObject):
|
|||
if self.is_disconnected():
|
||||
return # pragma: no cover
|
||||
if self.is_connecting() and not force:
|
||||
return
|
||||
return # pragma: no cover
|
||||
|
||||
# We need to set this before the event check, since stats polling
|
||||
# is independent of events
|
||||
|
|
|
@ -1377,7 +1377,7 @@ class vmmDomain(vmmLibvirtObject):
|
|||
start_job_progress_thread(self, meter, _("Saving domain to disk"))
|
||||
|
||||
if self.config.CLITestOptions.test_managed_save:
|
||||
time.sleep(3)
|
||||
time.sleep(1.2)
|
||||
self._backend.managedSave(0)
|
||||
|
||||
def has_managed_save(self):
|
||||
|
@ -1437,7 +1437,7 @@ class vmmDomain(vmmLibvirtObject):
|
|||
if self.conn.is_test() and "TESTSUITE-FAKE" in (dest_uri or ""):
|
||||
# If using the test driver and a special URI, fake successful
|
||||
# migration so we can test more of the migration wizard
|
||||
time.sleep(3)
|
||||
time.sleep(1.2)
|
||||
if not xml:
|
||||
xml = self.get_xml_to_define()
|
||||
destconn.define_domain(xml).create()
|
||||
|
|
Loading…
Reference in New Issue