hardware_testbench: run Crontrollers loop in thread, not the test

This commit is contained in:
Robert Jördens 2016-01-27 18:45:08 -07:00
parent 99f788965e
commit 1b7020dff3
3 changed files with 33 additions and 32 deletions

View File

@ -170,9 +170,9 @@ class Controllers:
elif action == "del": elif action == "del":
await self.active[param].end() await self.active[param].end()
del self.active[param] del self.active[param]
else:
raise ValueError
self.queue.task_done() self.queue.task_done()
if action not in ("set", "del"):
raise ValueError
def __setitem__(self, k, v): def __setitem__(self, k, v):
if (isinstance(v, dict) and v["type"] == "controller" and if (isinstance(v, dict) and v["type"] == "controller" and

View File

@ -6,7 +6,7 @@ import sys
import unittest import unittest
import logging import logging
import asyncio import asyncio
import atexit import threading
from artiq.master.databases import DeviceDB, DatasetDB from artiq.master.databases import DeviceDB, DatasetDB
from artiq.master.worker_db import DeviceManager, DatasetManager from artiq.master.worker_db import DeviceManager, DatasetManager
@ -30,15 +30,34 @@ class ControllerCase(unittest.TestCase):
else: else:
self.loop = asyncio.new_event_loop() self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop) asyncio.set_event_loop(self.loop)
atexit.register(self.loop.close) self.addCleanup(self.loop.close)
self.loop_thread = threading.Thread(target=self.loop.run_forever)
self.addCleanup(self.loop_thread.join)
self.addCleanup(self.loop.call_soon_threadsafe, self.loop.stop)
self.controllers = Controllers() self.controllers = Controllers()
self.controllers.host_filter = self.host_filter self.controllers.host_filter = self.host_filter
self.addCleanup(self._stop_controllers)
self.device_db = DeviceDB(os.path.join(artiq_root, "device_db.pyon")) self.device_db = DeviceDB(os.path.join(artiq_root, "device_db.pyon"))
self.device_mgr = DeviceManager(self.device_db) self.device_mgr = DeviceManager(self.device_db)
self.addCleanup(self.device_mgr.close_devices)
self.loop_thread.start()
def _stop_controllers(self):
fut = asyncio.run_coroutine_threadsafe(self.controllers.shutdown(),
self.loop)
fut.result()
async def _start(self, *names):
print("FOOO started")
l = asyncio.get_event_loop_policy()
l = l.get_event_loop()
print("FOOO started")
async def start(self, *names):
for name in names: for name in names:
try: try:
self.controllers[name] = self.device_db.get(name) self.controllers[name] = self.device_db.get(name)
@ -46,10 +65,10 @@ class ControllerCase(unittest.TestCase):
raise unittest.SkipTest( raise unittest.SkipTest(
"controller `{}` not found".format(name)) "controller `{}` not found".format(name))
await self.controllers.queue.join() await self.controllers.queue.join()
await asyncio.wait([asyncio.ensure_future(self.wait_for_ping(name)) await asyncio.wait([self._wait_for_ping(name)
for name in names]) for name in names])
async def wait_for_ping(self, name, retries=5): async def _wait_for_ping(self, name, retries=5):
t = self.timeout t = self.timeout
dt = t/retries dt = t/retries
while t > 0: while t > 0:
@ -68,27 +87,9 @@ class ControllerCase(unittest.TestCase):
t -= dt t -= dt
raise asyncio.TimeoutError raise asyncio.TimeoutError
def start_controllers(self, *names):
def with_controllers(*names): fut = asyncio.run_coroutine_threadsafe(self._start(*names), self.loop)
def wrapper(func): fut.result()
def inner(self):
try:
for name in names:
setattr(self, name, self.device_mgr.get(name))
func(self)
finally:
self.device_mgr.close_devices()
def wrapped_test(self):
try:
self.loop.run_until_complete(self.start(*names))
self.loop.run_until_complete(self.loop.run_in_executor(
None, inner, self))
finally:
self.loop.run_until_complete(self.controllers.shutdown())
return wrapped_test
return wrapper
@unittest.skipUnless(artiq_root, "no ARTIQ_ROOT") @unittest.skipUnless(artiq_root, "no ARTIQ_ROOT")

View File

@ -2,7 +2,7 @@ import unittest
from artiq.devices.lda.driver import Ldasim from artiq.devices.lda.driver import Ldasim
from artiq.language.units import dB from artiq.language.units import dB
from artiq.test.hardware_testbench import ControllerCase, with_controllers from artiq.test.hardware_testbench import ControllerCase
class GenericLdaTest: class GenericLdaTest:
@ -18,10 +18,10 @@ class GenericLdaTest:
class TestLda(ControllerCase, GenericLdaTest): class TestLda(ControllerCase, GenericLdaTest):
@with_controllers("lda") def setUp(self):
def test_attenuation(self): ControllerCase.setUp(self)
self.start_controllers("lda")
self.cont = self.device_mgr.get("lda") self.cont = self.device_mgr.get("lda")
GenericLdaTest.test_attenuation(self)
class TestLdaSim(GenericLdaTest, unittest.TestCase): class TestLdaSim(GenericLdaTest, unittest.TestCase):