uitests: More work to drop sleeping and hacks

Signed-off-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
Cole Robinson 2020-09-20 10:07:15 -04:00
parent ba08f84b34
commit 092a62552c
20 changed files with 220 additions and 193 deletions

View File

@ -2,7 +2,6 @@
# See the COPYING file in the top-level directory.
import re
import time
from gi.repository import Gdk
@ -17,16 +16,20 @@ class _FuzzyPredicate(dogtail.predicate.Predicate):
"""
Object dogtail/pyatspi want for node searching.
"""
def __init__(self, name=None, roleName=None, labeller_text=None):
def __init__(self, name=None, roleName=None, labeller_text=None,
focusable=False, onscreen=False):
"""
:param name: Match node.name or node.labeller.text if
labeller_text not specified
:param roleName: Match node.roleName
:param labeller_text: Match node.labeller.text
:param focusable: Ensure node is focusable
"""
self._name = name
self._roleName = roleName
self._labeller_text = labeller_text
self._focusable = focusable
self._onscreen = onscreen
self._name_pattern = None
self._role_pattern = None
@ -67,6 +70,12 @@ class _FuzzyPredicate(dogtail.predicate.Predicate):
if (self._labeller_text and
not self._labeller_pattern.match(labeller)):
return
if (self._focusable and not
(node.focusable and
node.onscreen and
node.sensitive and
node.roleName not in ["page tab list", "radio button"])):
return False
return True
except Exception as e:
log.debug(
@ -74,6 +83,16 @@ class _FuzzyPredicate(dogtail.predicate.Predicate):
self._name, self._roleName, self._labeller_text, e)
def _debug_decorator(fn):
def _cb(self, *args, **kwargs):
try:
return fn(self, *args, **kwargs)
except Exception:
print("node=%s\nstates=%s" % (self, self.print_states()))
raise
return _cb
class _VMMDogtailNode(dogtail.tree.Node):
"""
Our extensions to the dogtail node wrapper class.
@ -106,18 +125,28 @@ class _VMMDogtailNode(dogtail.tree.Node):
self.position[1] >= 0 and
self.position[1] + self.size[1] < screen.get_height())
@_debug_decorator
def check_onscreen(self):
"""
Check in a loop that the widget is onscreen
"""
utils.check(lambda: self.onscreen)
@_debug_decorator
def check_not_onscreen(self):
"""
Check in a loop that the widget is not onscreen
"""
utils.check(lambda: not self.onscreen)
@_debug_decorator
def check_focused(self):
"""
Check in a loop that the widget is focused
"""
utils.check(lambda: self.focused)
@_debug_decorator
def check_sensitive(self):
"""
Check whether interactive widgets are sensitive or not
@ -192,16 +221,6 @@ class _VMMDogtailNode(dogtail.tree.Node):
clickX, clickY = self.title_coordinates()
dogtail.rawinput.click(clickX, clickY, button)
def drag(self, x, y):
"""
Drag a window to the x/y coordinates
"""
time.sleep(.5)
self.click_title()
time.sleep(.5)
clickX, clickY = self.title_coordinates()
dogtail.rawinput.drag((clickX, clickY), (x, y))
def click(self, *args, **kwargs):
"""
click wrapper, give up to a second for widget to appear on
@ -243,32 +262,45 @@ class _VMMDogtailNode(dogtail.tree.Node):
def window_maximize(self):
assert self.roleName in ["frame", "dialog"]
utils.check(lambda: self.active)
self.click_title()
self.grab_focus()
s1 = self.size
self.keyCombo("<alt>F10")
utils.check(lambda: self.size != s1)
self.grabFocus()
self.grab_focus()
def window_close(self):
assert self.roleName in ["frame", "alert", "dialog"]
self.click_title()
utils.check(lambda: self.active)
assert self.roleName in ["frame", "alert", "dialog", "file chooser"]
self.grab_focus()
self.keyCombo("<alt>F4")
utils.check(lambda: not self.showing)
def window_find_focusable_child(self):
return self.find(None, focusable=True)
def grab_focus(self):
if self.roleName in ["frame", "alert", "dialog", "file chooser"]:
child = self.window_find_focusable_child()
child.grab_focus()
utils.check(lambda: self.active)
return
self.check_onscreen()
assert self.focusable
self.grabFocus()
self.check_focused()
#########################
# Widget search helpers #
#########################
def find(self, name, roleName=None, labeller_text=None,
check_active=True, recursive=True):
check_active=True, recursive=True, focusable=False):
"""
Search root for any widget that contains the passed name/role regex
strings.
"""
pred = _FuzzyPredicate(name, roleName, labeller_text)
pred = _FuzzyPredicate(name, roleName, labeller_text, focusable)
try:
ret = self.findChild(pred, recursive=recursive)

View File

@ -229,13 +229,16 @@ class VMMDogtailApp(object):
self.open()
return self._topwin
def error_if_already_running(self):
# Ensure virt-manager isn't already running
def has_dbus(self):
dbus = Gio.DBusProxy.new_sync(
Gio.bus_get_sync(Gio.BusType.SESSION, None), 0, None,
"org.freedesktop.DBus", "/org/freedesktop/DBus",
"org.freedesktop.DBus", None)
if "org.virt-manager.virt-manager" in dbus.ListNames():
return "org.virt-manager.virt-manager" in dbus.ListNames()
def error_if_already_running(self):
# Ensure virt-manager isn't already running
if self.has_dbus():
raise RuntimeError("virt-manager is already running. "
"Close it before running this test suite.")

View File

@ -14,7 +14,7 @@ def testShowNewVM(app):
uri="test:///default",
extra_opts=["--show-domain-creator"])
lib.utils.check(lambda: app.topwin.name == "New VM")
app.topwin.keyCombo("<alt>F4")
app.topwin.window_close()
app.wait_for_exit()
@ -26,7 +26,7 @@ def testShowHost(app):
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.topwin.window_close()
app.wait_for_exit()
@ -39,7 +39,7 @@ def testShowDetails(app):
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.topwin.window_close()
app.wait_for_exit()
@ -80,7 +80,6 @@ def testShowDelete(app):
app.wait_for_exit()
def testShowRemoteDBusConnect(app):
"""
Test the remote app dbus connection
@ -130,14 +129,12 @@ def testShowCLIError(app):
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")
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")
@ -158,27 +155,25 @@ def testCLIFirstRunNoLibvirtd(app):
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)
extra_opts=["--trace-libvirt=mainloop",
"--test-options=short-poll"])
app.sleep(.5) # Give time for polling to trigger
lib.utils.check(lambda: app.topwin.active)
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")
extra_opts=["--test-options=leak-debug",
"--test-options=short-poll"])
app.sleep(.5) # Give time for polling to trigger
app.topwin.window_close()
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)
@ -187,10 +182,8 @@ def testCLINoFork(app):
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)
app.topwin.window_close()
lib.utils.check(lambda: not app.has_dbus())
def testCLIGTKArgs(app):

View File

@ -98,24 +98,27 @@ def testCloneMulti(app):
# Clone 'test-clone', check some results, make sure clone works
manager = app.topwin
manager.window_maximize()
# Shutdown this VM to prep for later
manager.find("test-many-devices").click()
sbutton = manager.find("Shut Down", "push button")
sbutton.click()
lib.utils.check(lambda: not sbutton.sensitive)
# Do a basic clone
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")
manager.find("test-clone1", "table cell")
# 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()
manager.grab_focus()
app.manager_conn_disconnect("test testdriver.xml")
lib.utils.check(lambda: not win.showing)
@ -190,8 +193,7 @@ def testCloneError(app):
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.window_close()
win = app.manager_open_clone("test-clone-simple")
badname = "test/foo"
@ -229,8 +231,7 @@ def testCloneNonmanaged(app):
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.window_close()
lib.utils.check(lambda: manager.active)
win = app.manager_open_clone("test-clone-simple")

View File

@ -25,17 +25,17 @@ def testConnectionBlacklist(app):
_delete_vm("test-arm-kernel")
_delete_vm("test-clone-full")
_delete_vm("test-clone-simple")
app.sleep(.5)
app.sleep(.5) # Give events time to register to hit full blacklist path
lib.utils.check(
lambda: "test-many-devices" not in app.topwin.fmt_nodes())
def testConnectionConnCrash(app):
app.open(
extra_opts=["--test-options=conn-crash"])
extra_opts=["--test-options=conn-crash",
"--test-options=short-poll"])
manager = app.topwin
app.sleep(1)
manager.find(r"^test testdriver.xml - Not Connected", "table cell")
lib.utils.check(lambda: manager.active)
@ -43,9 +43,10 @@ def testConnectionConnCrash(app):
def testConnectionFakeEvents(app):
app.open(
extra_opts=["--test-options=fake-nodedev-event=computer",
"--test-options=fake-agent-event=test-many-devices"])
"--test-options=fake-agent-event=test-many-devices",
"--test-options=short-poll"])
manager = app.topwin
app.sleep(2.5)
app.sleep(1.2) # needs a second to hit both nodedev/agent event paths
lib.utils.check(lambda: manager.active)

View File

@ -18,20 +18,36 @@ def _open_newvm(app):
return app.find_window("New VM")
def _forward(newvm, check=True):
def _nav(newvm, forward, back, check):
pagenumlabel = newvm.find("pagenum-label")
oldtext = pagenumlabel.text
newvm.find_fuzzy("Forward", "button").click()
ignore = back
# Clicking is tough to manage, because when clicking
# rapidly in succession the create wizard has a few
# cases of stealing focus to better help the user
# navigate the wizard, but this is very racy and
# tough to deal with hear. Luckily accelerators
# don't care too much about focus
if forward:
button = newvm.find("Forward", "push button")
combo = "<alt>f"
else:
button = newvm.find("Back", "push button")
combo = "<alt>b"
button.check_onscreen()
button.keyCombo(combo)
if check:
lib.utils.check(lambda: pagenumlabel.text != oldtext)
def _forward(newvm, check=True):
_nav(newvm, forward=True, back=False, check=check)
def _back(newvm, check=True):
pagenumlabel = newvm.find("pagenum-label")
oldtext = pagenumlabel.text
newvm.find_fuzzy("Back", "button").click()
if check:
lib.utils.check(lambda: pagenumlabel.text != oldtext)
_nav(newvm, forward=False, back=True, check=check)
############################################
@ -51,7 +67,7 @@ def testNewVMMultiConnection(app):
app.manager_conn_disconnect("test testdriver.xml")
newvm = _open_newvm(app)
newvm.find_fuzzy("No active connection to install on")
newvm.keyCombo("<alt>F4")
newvm.window_close()
lib.utils.check(lambda: manager.active)
# Check the xen PV only startup warning
@ -63,18 +79,14 @@ def testNewVMMultiConnection(app):
_add_conn(tests.utils.URIs.kvm + _capsopt("test-empty.xml"))
newvm = _open_newvm(app)
newvm.find(".*No hypervisor options were found.*KVM kernel modules.*")
newvm.click()
newvm.click_title()
newvm.keyCombo("<alt>F4")
newvm.window_close()
app.manager_conn_disconnect("QEMU/KVM")
_add_conn(tests.utils.URIs.kvm_session +
_capsopt("test-qemu-no-kvm.xml"))
newvm = _open_newvm(app)
newvm.find(".*KVM is not available.*")
newvm.click()
newvm.click_title()
newvm.keyCombo("<alt>F4")
newvm.window_close()
_add_conn(tests.utils.URIs.lxc)
_add_conn(tests.utils.URIs.test_full)
@ -100,8 +112,7 @@ def testNewVMMultiConnection(app):
_forward(newvm)
# Back up, select test:///default, verify media-combo is now empty
newvm.click_title()
newvm.keyCombo("<alt>F4")
newvm.window_close()
newvm = _open_newvm(app)
newvm.combo_select("create-conn", ".*test default.*")
_forward(newvm)
@ -137,22 +148,13 @@ def testNewVMManualDefault(app):
lib.utils.check(lambda: osentry.text == "Generic OS")
# Verify back+forward still keeps Generic selected
app.sleep(.5)
_back(newvm)
app.sleep(.5)
_forward(newvm)
app.sleep(.5)
lib.utils.check(lambda: "Generic" in osentry.text)
osentry.check_onscreen()
# The sleeps shouldn't be required, but this test continues to be
# flakey, so this is an attempt to fix it.
_forward(newvm)
app.sleep(.5)
_forward(newvm)
app.sleep(.5)
_forward(newvm)
app.sleep(.5)
# Empty triggers a specific codepath
@ -236,8 +238,13 @@ def testNewVMCDROMRegular(app):
# Catch validation error
entry = newvm.find("media-entry")
lib.utils.check(lambda: "/dev/sr0" in entry.text)
entry.click()
entry.set_text("")
# Something about entry.set_text is flakey with focus,
# this stuff is to try and fix focus
app.rawinput.pressKey("Escape")
newvm.click_title()
_forward(newvm, check=False)
app.click_alert_button("media selection is required", "OK")
@ -428,7 +435,7 @@ def testNewVMURL(app):
lib.utils.check(lambda: not newvm.showing)
# Re-run the newvm wizard, check that URL was remembered
details.keyCombo("<alt>F4")
details.window_close()
newvm = _open_newvm(app)
newvm.find_fuzzy("Network Install", "radio").click()
_forward(newvm)
@ -643,12 +650,9 @@ def testNewVMArmKernel(app):
local = newvm.find_fuzzy("Local", "radio")
lib.utils.check(lambda: not local.sensitive)
newvm.find_fuzzy("Machine Type", "combo").click()
app.sleep(.2)
newvm.find_fuzzy("canon", "menu item").click()
newvm.find_fuzzy("Machine Type", "combo").click()
app.sleep(.2)
newvm.find("virt", "menu item").click()
app.sleep(.5)
importradio = newvm.find("Import", "radio")
importradio.click()
lib.utils.check(lambda: importradio.checked)
@ -1181,14 +1185,13 @@ def testNewVMSession(app):
newvm.find_fuzzy("Finish", "button").click()
details = app.find_details_window("vm1")
lib.utils.check(lambda: not newvm.showing)
app.sleep(1)
details.window_close()
# Ensure disconnecting will close the dialog
manager = app.topwin
manager.window_maximize()
newvm = _open_newvm(app)
manager.click_title()
manager.grab_focus()
app.manager_conn_disconnect(".*session.*")
lib.utils.check(lambda: not newvm.showing)

View File

@ -79,7 +79,7 @@ def testCreateVolMisc(app):
browsewin.find("Browse Local", "push button").click()
chooser = app.root.find(
"Locate existing storage", "file chooser")
chooser.keyCombo("<alt>F4")
chooser.window_close()
app.select_storagebrowser_volume(
"default-pool", "bochs-vol", doubleclick=True)
backingstore = win.find("backing-store")

View File

@ -211,7 +211,6 @@ def testDeleteSkipStorage(app):
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")
@ -237,13 +236,11 @@ def testDeleteDeviceNoStorage(app):
chk = delete.find("Delete associated", "check box")
lib.utils.check(lambda: not chk.checked)
_finish(app, delete, [])
details.click()
details.keyCombo("<alt>F4")
details.window_close()
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")
@ -271,8 +268,7 @@ def testDeleteDeviceWithStorage(app):
path = "/dev/default-pool/overlay.img"
delete.find_fuzzy(path)
_finish(app, delete, [path])
details.click()
details.keyCombo("<alt>F4")
details.window_close()
browser = _open_storage_browser(app)
browser.find_fuzzy("default-pool", "table cell").click()
@ -304,12 +300,10 @@ def testDeleteDeviceFail(app):
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")
details.window_close()
# 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")

View File

@ -64,8 +64,7 @@ def testDetailsHardwareSmokeTestAlternate(app):
win = _testSmokeTest(app, "test alternate devs title")
win.find("Details", "page tab").click()
_select_hw(app, win, "Performance", "performance-tab")
# Wait for perf signals to trigger, to cover more code
app.sleep(2)
app.sleep(.2) # wait for polling to trigger perf updates
def _testRename(app, win, origname, newname):
@ -128,8 +127,7 @@ def testDetailsStateMisc(app):
# View Manager option
win.find("File", "menu").click()
win.find("View Manager", "menu item").click()
lib.utils.check(lambda: app.topwin.active)
app.topwin.keyCombo("<alt>F4")
app.topwin.window_close()
lib.utils.check(lambda: win.active)
# Make a change and then trigger unapplied change warning
@ -443,9 +441,8 @@ def testDetailsNetIPAddress(app):
tab.find("IP address:", "push button").click()
check_ip("10.0.0.3")
win.keyCombo("<alt>F4")
lib.utils.check(lambda: not win.showing)
app.topwin.click_title()
win.window_close()
app.topwin.grab_focus()
# Tests the fake qemu guest agent path
win = app.manager_open_details("test alternate devs title")

View File

@ -174,7 +174,7 @@ def testHostConn(app):
manager.find("FOOBAR", "table cell")
# Close the manager
manager.keyCombo("<alt>F4")
manager.window_close()
lib.utils.check(lambda: win.active)
# Quit app from the file menu

View File

@ -40,8 +40,7 @@ def testInspectionMock(app):
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.window_close()
# Open a VM with no disks which will report an inspection error
app.root.find_fuzzy("test\n", "table cell").doubleClick()
@ -53,8 +52,10 @@ def testInspectionMock(app):
# Closing and reopening a connection triggers some libguest
# cache reading
details.keyCombo("<alt>F4")
details.window_close()
manager.click()
c = manager.find("test testdriver.xml", "table cell")
app.manager_conn_disconnect("test testdriver.xml")
lib.utils.check(lambda: "Not Connected" in c.text)
app.manager_conn_connect("test testdriver.xml")
app.sleep(2)
lib.utils.check(lambda: "Not Connected" not in c.text)

View File

@ -62,6 +62,7 @@ def _checkConsoleStandard(app, dom):
"""
Shared logic for general console handling
"""
ignore = dom
win = app.topwin
con = win.find("console-gfx-viewport")
lib.utils.check(lambda: con.showing)
@ -134,17 +135,7 @@ def _checkConsoleStandard(app, dom):
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)
win.window_close()
@_vm_wrapper("uitests-vnc-standard")
@ -157,6 +148,37 @@ def testConsoleSpiceStandard(app, dom):
return _checkConsoleStandard(app, dom)
def _checkConsoleFocus(app, dom):
"""
Shared logic for console keyboard grab handling
"""
win = app.topwin
con = win.find("console-gfx-viewport")
lib.utils.check(lambda: con.showing)
# Check that modifiers don't work when console grabs pointer
win.click()
app.sleep(.5) # make sure window code has time to adjust modifiers
win.keyCombo("<ctrl>w")
lib.utils.check(lambda: win.showing)
dom.destroy()
win.find("Guest is not running.")
win.grab_focus()
app.sleep(.5) # make sure window code has time to adjust modifiers
win.keyCombo("<ctrl>w")
lib.utils.check(lambda: not win.showing)
@_vm_wrapper("uitests-vnc-standard")
def testConsoleVNCFocus(app, dom):
return _checkConsoleFocus(app, dom)
@_vm_wrapper("uitests-spice-standard")
def testConsoleSpiceFocus(app, dom):
return _checkConsoleFocus(app, dom)
def _checkPassword(app):
"""
Shared logic for password handling
@ -247,8 +269,7 @@ def testConsoleVNCSocket(app, dom):
vmenu.click()
tmenu = win.find("Consoles", "menu")
tmenu.point()
# We need to sleep to give the menu time to dynamically populate
app.sleep(.5)
app.sleep(.5) # give console menu time to dynamically populate
tmenu.find(msg, "radio menu item").click()
# A bit of an extra test, make sure selecting Graphical Console works
@ -270,10 +291,14 @@ def testConsoleAutoconnect(app, dom):
vmenu.click()
vmenu.find("Autoconnect").click()
dom.destroy()
app.sleep(1)
label = win.find("Guest is not running.")
label.check_onscreen()
dom.create()
label.check_not_onscreen()
button = win.find("Connect to console", "push button")
button.check_onscreen()
lib.utils.check(lambda: not con.showing)
win.find("Connect to console", "push button").click()
button.click()
lib.utils.check(lambda: con.showing)
@ -282,7 +307,6 @@ 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)
@ -308,7 +332,7 @@ def testConsoleLXCSerial(app, dom):
textmenu = view.find("Consoles", "menu")
textmenu.point()
lib.utils.check(lambda: textmenu.showing)
app.sleep(.5)
app.sleep(.5) # give console menu time to dynamically populate
item = textmenu.find("Text Console 1")
lib.utils.check(lambda: not item.sensitive)
@ -324,8 +348,9 @@ def testConsoleLXCSerial(app, dom):
lib.utils.check(lambda: win.showing)
# Shut it down, ensure <ctrl>w works again
_destroy(app, win)
lib.utils.check(lambda: not dom.isActive())
win.click_title()
app.sleep(1)
app.sleep(.3) # make sure window code has time to adjust modifiers
win.keyCombo("<ctrl>w")
lib.utils.check(lambda: not win.showing)
@ -368,6 +393,7 @@ def testConsoleSpiceSpecific(app, dom):
smenu.point()
smenu.find("Auto resize VM", "check menu item").click()
_click_auto()
win.click_title()
win.window_maximize()
_click_auto()
win.click_title()

View File

@ -50,16 +50,8 @@ def testVMLifecycle(app):
def testVMNoEventsLifecycle(app):
app.open(extra_opts=["--test-options=no-events"])
# 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()
app.open(extra_opts=["--test-options=no-events",
"--test-options=short-poll"])
_testVMLifecycle(app)
@ -161,14 +153,14 @@ def testManagerQEMUSetTime(app):
smenu.click()
save.click()
lib.utils.check(lambda: run.sensitive)
app.sleep(1)
app.sleep(1) # give settime thread time to run
run.click()
lib.utils.check(lambda: not run.sensitive)
app.sleep(1)
app.sleep(1) # give settime thread time to run
smenu.click()
save.click()
lib.utils.check(lambda: run.sensitive)
app.sleep(1)
app.sleep(1) # give settime thread time to run
def testManagerVMRunFail(app):
@ -239,7 +231,7 @@ def testManagerWindowReposition(app):
manager.window_maximize()
newx = manager.position[0]
newy = manager.position[1]
manager.keyCombo("<alt>F4")
manager.window_close()
host.click_title()
host.find("File", "menu").click()
host.find("View Manager", "menu item").click()
@ -253,14 +245,7 @@ def testManagerWindowCleanup(app):
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 = app.topwin
app.sleep(1)
manager.window_maximize()
# Open delete window hitting a special code path, then close it
@ -268,8 +253,7 @@ def testManagerWindowCleanup(app):
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.find("storage-list").grab_focus()
delete.window_close()
# Open Clone window hitting a special code path, then close it
@ -277,30 +261,22 @@ def testManagerWindowCleanup(app):
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()
# Open host
manager.grab_focus()
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)
# Open details
manager.grab_focus()
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)
manager.grab_focus()
app.manager_conn_disconnect("test testdriver.xml")
# Ensure all those windows aren't showing

View File

@ -108,8 +108,7 @@ def testMigrateConnMismatch(app):
mig.find("conn-combo").find("No usable", "menu item")
# Test explicit dialog 'delete'
mig.keyCombo("<alt>F4")
lib.utils.check(lambda: not mig.showing)
mig.window_close()
# Ensure disconnecting will close the dialog
manager.click_title()

View File

@ -92,7 +92,6 @@ def testPrefsAll(app):
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")
@ -104,8 +103,7 @@ def testPrefsXMLEditor(app):
xmleditor.typeText("1234abcd")
lib.utils.check(lambda: xmleditor.text == origtext)
managerwin.click_title()
managerwin.grabFocus()
managerwin.grab_focus()
managerwin.find("Edit", "menu").click()
managerwin.find("Preferences", "menu item").click()
prefswin = app.find_window("Preferences")
@ -113,8 +111,8 @@ def testPrefsXMLEditor(app):
prefswin.find_fuzzy("Close", "push button").click()
lib.utils.check(lambda: prefswin.visible is False)
managerwin.keyCombo("<alt>F4")
detailswin.click()
managerwin.window_close()
detailswin.grab_focus()
newtext = xmleditor.text.replace(">", "><title>FOOTITLE</title>", 1)
xmleditor.set_text(newtext)
finish.click()

View File

@ -12,19 +12,19 @@ from . import lib
def testSystrayFake(app):
app.open(
keyfile="systray.ini",
extra_opts=["--test-options=fake-systray"],
window_name="Virtual Machine Manager")
extra_opts=["--test-options=fake-systray"])
manager = app.topwin
systray = app.root.find("vmm-fake-systray", check_active=False)
manager.drag(1000, 1000)
systray.grab_focus()
manager = app.root.find("Virtual Machine Manager", check_active=False)
# Add a connection to trigger systray update
uri = tests.utils.URIs.kvm
manager.grab_focus()
app.manager_createconn(uri=uri)
# Hide the manager
systray.click_title()
systray.grab_focus()
systray.click()
lib.utils.check(lambda: not manager.showing)
lib.utils.check(lambda: app.is_running())
@ -81,12 +81,13 @@ def testSystrayFake(app):
_check_vm_action("QEMU/KVM", "test-arm-kernel", "Resume")
# Reshow the manager
systray.grab_focus()
systray.click()
lib.utils.check(lambda: manager.showing)
lib.utils.check(lambda: app.is_running())
# Close from the menu
systray.click_title()
systray.grab_focus()
systray.click(button=3)
menu = app.root.find("vmm-systray-menu")
menu.find("Quit", "menu item").click()
@ -97,21 +98,22 @@ def testSystrayFake(app):
def testSystrayToggle(app):
app.open(
keyfile="systray.ini",
extra_opts=["--test-options=fake-systray"],
window_name="Virtual Machine Manager")
extra_opts=["--test-options=fake-systray"])
manager = app.topwin
systray = app.root.find("vmm-fake-systray", check_active=False)
systray.grab_focus()
manager = app.root.find("Virtual Machine Manager", check_active=False)
manager.grab_focus()
manager.find("Edit", "menu").click()
manager.find("Preferences", "menu item").click()
prefs = app.find_window("Preferences")
# Close the system tray
prefs.click_title()
prefs.grab_focus()
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")
manager.window_close()
lib.utils.check(lambda: not app.is_running())

View File

@ -432,6 +432,8 @@ class vmmConfig(object):
def get_stats_history_length(self):
return 120
def get_stats_update_interval(self):
if self.CLITestOptions.short_poll:
return .1
interval = self.conf.get("/stats/update-interval")
return max(interval, 1)
def set_stats_update_interval(self, interval):

View File

@ -73,7 +73,7 @@ def schedule_fake_agent_event(conn, cb):
dom = backend.lookupByName(vmname)
cb(backend, dom, state, reason, None)
conn.timeout_add(1000, time_cb)
conn.timeout_add(500, time_cb)
def schedule_fake_nodedev_event(conn, lifecycle_cb, update_cb):
@ -91,8 +91,8 @@ def schedule_fake_nodedev_event(conn, lifecycle_cb, update_cb):
nodedev = backend.nodeDeviceLookupByName(nodename)
update_cb(backend, nodedev, None)
conn.timeout_add(1000, lifecycle_cb_wrapper)
conn.timeout_add(2000, update_cb_wrapper)
conn.timeout_add(500, lifecycle_cb_wrapper)
conn.timeout_add(1000, update_cb_wrapper)
def fake_openauth(conn, cb, data):
@ -167,6 +167,8 @@ class CLITestOptionsClass:
for testing the TCP URI auth dialog
* fake-session-error: Fake a connection open error that
triggers logind session lookup
* short-poll: Use a polling interval of only .1 seconds to speed
up the uitests a bit
"""
def __init__(self, test_options_str):
optset = set()
@ -211,6 +213,7 @@ class CLITestOptionsClass:
self.fake_nodedev_event = _get_value("fake-nodedev-event")
self.fake_openauth = _get("fake-openauth")
self.fake_session_error = _get("fake-session-error")
self.short_poll = _get("short-poll")
if optset: # pragma: no cover
raise RuntimeError("Unknown --test-options keys: %s" % optset)

View File

@ -804,7 +804,7 @@ class vmmManager(vmmGObjectUI):
def popup_vm_menu_key(self, widget_ignore, event):
if Gdk.keyval_name(event.keyval) != "Menu":
return False
return False # pragma: no cover
model, treeiter = self.widget("vm-list").get_selection().get_selected()
self.popup_vm_menu(model, treeiter, event)

View File

@ -166,17 +166,13 @@ class _SystrayWindow(_Systray):
self._init_ui()
def _init_ui(self):
image = Gtk.Image()
image.set_from_stock(Gtk.STOCK_ADD, Gtk.IconSize.DIALOG)
box = Gtk.EventBox()
box.add(image)
box.connect("button-press-event", self._popup_cb)
button = Gtk.Button.new_from_stock(Gtk.STOCK_ADD)
button.connect("button-press-event", self._popup_cb)
self._window = Gtk.Window()
self._window.set_size_request(100, 100)
self._window.get_accessible().set_name("vmm-fake-systray")
self._window.add(box)
self._window.add(button)
def is_embedded(self):
return self._window.is_visible()