testing: use Murphy to control resource access during testing
When multiple different runtests.py instances are active, they must coordinate access to shared resources like accounts on servers. We can use Murphy (https://01.org/murphy/) for that. If runtest.py is started with a D-Bus session address set in the environment, it expects Murphy to be running there and will lock a resource named after each operation before running the operation. Some operations (like "compile") can be granted to each instance, but some (like "memotoo") must be exclusive. Here's a complete Murphy lua config: m = murphy.get() -- try loading console plugin m:try_load_plugin('console') -- load the native resource plugin if m:plugin_exists('resource-native') then m:load_plugin('resource-native') m:info("native resource plugin loaded") else m:info("No native resource plugin found...") end -- load the dbus resource plugin m:try_load_plugin('resource-dbus', { dbus_bus = "session", dbus_service = "org.Murphy", dbus_track = true, default_zone = "driver", default_class = "implicit" }) m:info("dbus resource plugin loaded") -- define application classes application_class { name="implicit" , priority=0 , modal=false, share=true , order="fifo" } -- define zone attributes zone.attributes { } -- define zones zone { name = "driver" } -- define resource classes resource.class { name = "audio_playback", shareable = true, attributes = { role = { mdb.string, "music", "rw" }, pid = { mdb.string, "<unknown>", "rw" }, policy = { mdb.string, "relaxed", "rw" } } } -- SyncEvolution resources: one per runtest.py -- Some tests can run in parallel. Those resources are shareable. for i,v in pairs { -- compiling the source on one platform "compile", "install", "dist", -- checking out source "libsynthesis", "syncevolution", "activesyncd", -- local tests "evolution", "dbus", "pim", } do resource.class { name = v, shareable = true } end -- TODO (in runtests.py): some of these resources overlap for i,v in pairs { -- tests involving unique peers "googlecalendar", "googlecontacts", "owndrive", "yahoo", "oracle", "davical", "apple", "googleeas", "exchange", "edsfile", "edseds", "edsxfile", "davfile", "edsdav", "mobical", "memotoo", } do resource.class { name = v, shareable = false } end -- test for creating selections: don't remove, murphyd won't start without it -- (E: Failed to enable resolver autoupdate.) mdb.select { name = "audio_owner", table = "audio_playback_owner", columns = {"application_class"}, condition = "zone_name = 'driver'", }
This commit is contained in:
parent
28c0f6d923
commit
f28861884e
1 changed files with 80 additions and 0 deletions
|
@ -27,6 +27,30 @@ def log(format, *args):
|
|||
log.start = time.time()
|
||||
log.latest = log.start
|
||||
|
||||
# Murphy support: as a first step, lock one resource named like the
|
||||
# test before running the test.
|
||||
gobject = None
|
||||
try:
|
||||
import gobject
|
||||
except ImportError:
|
||||
try:
|
||||
from gi.repository import GObject as gobject
|
||||
except ImportError:
|
||||
pass
|
||||
import dbus
|
||||
from dbus.mainloop.glib import DBusGMainLoop
|
||||
DBusGMainLoop(set_as_default=True)
|
||||
if 'DBUS_SESSION_BUS_ADDRESS' in os.environ:
|
||||
bus = dbus.SessionBus()
|
||||
loop = gobject.MainLoop()
|
||||
murphy = dbus.Interface(bus.get_object('org.Murphy', '/org/murphy/resource'), 'org.murphy.manager')
|
||||
log('using murphy')
|
||||
else:
|
||||
bus = None
|
||||
loop = None
|
||||
murphy = None
|
||||
log('not using murphy')
|
||||
|
||||
try:
|
||||
import gzip
|
||||
havegzip = True
|
||||
|
@ -171,6 +195,8 @@ class Action:
|
|||
oldout = sys.stdout
|
||||
olderr = sys.stderr
|
||||
cwd = os.getcwd()
|
||||
resourceset = None
|
||||
locked = False
|
||||
try:
|
||||
subdirname = "%d-%s" % (step, self.name)
|
||||
del_dir(subdirname)
|
||||
|
@ -183,6 +209,48 @@ class Action:
|
|||
os.dup2(fd, 2)
|
||||
sys.stdout = os.fdopen(fd, "w", 0) # unbuffered output!
|
||||
sys.stderr = sys.stdout
|
||||
if murphy:
|
||||
log('=== locking resource %s ===', self.name)
|
||||
resourcesetpath = murphy.createResourceSet()
|
||||
resourceset = dbus.Interface(bus.get_object('org.Murphy', resourcesetpath), 'org.murphy.resourceset')
|
||||
resourcepath = resourceset.addResource(self.name)
|
||||
# Allow sharing of the resource. Only works if the resource
|
||||
# was marked as "shareable" in the murphy config, otherwise
|
||||
# we get exclusive access.
|
||||
resource = dbus.Interface(bus.get_object('org.Murphy', resourcepath), 'org.murphy.resource')
|
||||
resource.setProperty('shared', dbus.Boolean(True, variant_level=1))
|
||||
|
||||
# Track pending request separately, because status == 'pending'
|
||||
# either means something else ('unknown'?) or is buggy/unreliable.
|
||||
# See https://github.com/01org/murphy/issues/5
|
||||
pending = False
|
||||
def propertyChanged(prop, value):
|
||||
global pending
|
||||
log('property changed: %s = %s', prop, value)
|
||||
if prop == 'status':
|
||||
if value == 'acquired':
|
||||
# Success!
|
||||
loop.quit()
|
||||
elif value == 'lost':
|
||||
# Not yet?!
|
||||
log('Murphy request failed, waiting for resource to become available.')
|
||||
pending = False
|
||||
elif value == 'pending':
|
||||
pass
|
||||
elif value == 'available':
|
||||
if not pending:
|
||||
log('Murphy request may succeed now, try again.')
|
||||
resourceset.request()
|
||||
pending = True
|
||||
else:
|
||||
log('Unexpected status: %s', value)
|
||||
try:
|
||||
match = bus.add_signal_receiver(propertyChanged, 'propertyChanged', 'org.murphy.resourceset', 'org.Murphy', resourcesetpath)
|
||||
resourceset.request()
|
||||
pending = True
|
||||
loop.run()
|
||||
finally:
|
||||
match.remove()
|
||||
log('=== starting %s ===', self.name)
|
||||
self.execute()
|
||||
self.status = Action.DONE
|
||||
|
@ -191,6 +259,18 @@ class Action:
|
|||
traceback.print_exc()
|
||||
self.status = Action.FAILED
|
||||
self.summary = str(inst)
|
||||
finally:
|
||||
try:
|
||||
if locked:
|
||||
log('=== unlocking resource %s ===', self.name)
|
||||
resourceset.release()
|
||||
if resourceset:
|
||||
log('=== deleting resource set %s ===', self.name)
|
||||
resourceset.delete()
|
||||
if locked or resourceset:
|
||||
log('=== done with Murphy ===')
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
||||
log('\n=== %s: %s ===', self.name, self.status)
|
||||
sys.stdout.flush()
|
||||
|
|
Loading…
Reference in a new issue