From 1b7020dff36a7412f2dba05290219d073b72e4c6 Mon Sep 17 00:00:00 2001 From: Robert Jordens Date: Wed, 27 Jan 2016 18:45:08 -0700 Subject: [PATCH] hardware_testbench: run Crontrollers loop in thread, not the test --- artiq/devices/ctlmgr.py | 4 +-- artiq/test/hardware_testbench.py | 53 ++++++++++++++++---------------- artiq/test/lda.py | 8 ++--- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/artiq/devices/ctlmgr.py b/artiq/devices/ctlmgr.py index 416b9f7d1..0a09c7cb8 100644 --- a/artiq/devices/ctlmgr.py +++ b/artiq/devices/ctlmgr.py @@ -170,9 +170,9 @@ class Controllers: elif action == "del": await self.active[param].end() del self.active[param] - else: - raise ValueError self.queue.task_done() + if action not in ("set", "del"): + raise ValueError def __setitem__(self, k, v): if (isinstance(v, dict) and v["type"] == "controller" and diff --git a/artiq/test/hardware_testbench.py b/artiq/test/hardware_testbench.py index 1633fbc38..4f34fd3a9 100644 --- a/artiq/test/hardware_testbench.py +++ b/artiq/test/hardware_testbench.py @@ -6,7 +6,7 @@ import sys import unittest import logging import asyncio -import atexit +import threading from artiq.master.databases import DeviceDB, DatasetDB from artiq.master.worker_db import DeviceManager, DatasetManager @@ -30,15 +30,34 @@ class ControllerCase(unittest.TestCase): else: self.loop = asyncio.new_event_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.host_filter = self.host_filter + self.addCleanup(self._stop_controllers) self.device_db = DeviceDB(os.path.join(artiq_root, "device_db.pyon")) 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: try: self.controllers[name] = self.device_db.get(name) @@ -46,10 +65,10 @@ class ControllerCase(unittest.TestCase): raise unittest.SkipTest( "controller `{}` not found".format(name)) 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]) - async def wait_for_ping(self, name, retries=5): + async def _wait_for_ping(self, name, retries=5): t = self.timeout dt = t/retries while t > 0: @@ -68,27 +87,9 @@ class ControllerCase(unittest.TestCase): t -= dt raise asyncio.TimeoutError - -def with_controllers(*names): - def wrapper(func): - 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 + def start_controllers(self, *names): + fut = asyncio.run_coroutine_threadsafe(self._start(*names), self.loop) + fut.result() @unittest.skipUnless(artiq_root, "no ARTIQ_ROOT") diff --git a/artiq/test/lda.py b/artiq/test/lda.py index bf35ce8b9..cb35565b0 100644 --- a/artiq/test/lda.py +++ b/artiq/test/lda.py @@ -2,7 +2,7 @@ import unittest from artiq.devices.lda.driver import Ldasim from artiq.language.units import dB -from artiq.test.hardware_testbench import ControllerCase, with_controllers +from artiq.test.hardware_testbench import ControllerCase class GenericLdaTest: @@ -18,10 +18,10 @@ class GenericLdaTest: class TestLda(ControllerCase, GenericLdaTest): - @with_controllers("lda") - def test_attenuation(self): + def setUp(self): + ControllerCase.setUp(self) + self.start_controllers("lda") self.cont = self.device_mgr.get("lda") - GenericLdaTest.test_attenuation(self) class TestLdaSim(GenericLdaTest, unittest.TestCase):