2015-10-12 19:20:04 +08:00
|
|
|
# Copyright (C) 2015 M-Labs Limited
|
2015-09-07 06:08:57 +08:00
|
|
|
# Copyright (C) 2014, 2015 Robert Jordens <jordens@gmail.com>
|
|
|
|
|
2015-06-26 12:19:11 +08:00
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import unittest
|
|
|
|
import logging
|
2016-01-28 05:24:32 +08:00
|
|
|
import asyncio
|
2016-01-28 09:45:08 +08:00
|
|
|
import threading
|
2015-06-26 12:19:11 +08:00
|
|
|
|
2015-10-12 19:20:04 +08:00
|
|
|
from artiq.master.databases import DeviceDB, DatasetDB
|
|
|
|
from artiq.master.worker_db import DeviceManager, DatasetManager
|
2015-09-01 12:52:39 +08:00
|
|
|
from artiq.coredevice.core import CompileError
|
2015-07-14 04:08:20 +08:00
|
|
|
from artiq.frontend.artiq_run import DummyScheduler
|
2016-01-28 05:24:32 +08:00
|
|
|
from artiq.devices.ctlmgr import Controllers
|
2015-06-26 12:19:11 +08:00
|
|
|
|
|
|
|
|
|
|
|
artiq_root = os.getenv("ARTIQ_ROOT")
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2016-01-28 05:24:32 +08:00
|
|
|
@unittest.skipUnless(artiq_root, "no ARTIQ_ROOT")
|
|
|
|
class ControllerCase(unittest.TestCase):
|
|
|
|
host_filter = "::1"
|
|
|
|
timeout = 2
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
if os.name == "nt":
|
|
|
|
self.loop = asyncio.ProactorEventLoop()
|
2015-07-05 11:44:28 +08:00
|
|
|
else:
|
2016-01-28 05:24:32 +08:00
|
|
|
self.loop = asyncio.new_event_loop()
|
|
|
|
asyncio.set_event_loop(self.loop)
|
2016-01-28 09:45:08 +08:00
|
|
|
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)
|
2016-01-28 05:24:32 +08:00
|
|
|
|
|
|
|
self.controllers = Controllers()
|
|
|
|
self.controllers.host_filter = self.host_filter
|
2016-01-28 09:45:08 +08:00
|
|
|
self.addCleanup(self._stop_controllers)
|
2016-01-28 05:24:32 +08:00
|
|
|
|
|
|
|
self.device_db = DeviceDB(os.path.join(artiq_root, "device_db.pyon"))
|
|
|
|
self.device_mgr = DeviceManager(self.device_db)
|
2016-01-28 09:45:08 +08:00
|
|
|
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")
|
|
|
|
|
2016-01-28 05:24:32 +08:00
|
|
|
|
|
|
|
for name in names:
|
|
|
|
try:
|
|
|
|
self.controllers[name] = self.device_db.get(name)
|
|
|
|
except KeyError:
|
|
|
|
raise unittest.SkipTest(
|
|
|
|
"controller `{}` not found".format(name))
|
|
|
|
await self.controllers.queue.join()
|
2016-01-28 09:45:08 +08:00
|
|
|
await asyncio.wait([self._wait_for_ping(name)
|
2016-01-28 05:24:32 +08:00
|
|
|
for name in names])
|
|
|
|
|
2016-01-28 09:45:08 +08:00
|
|
|
async def _wait_for_ping(self, name, retries=5):
|
2016-01-28 05:24:32 +08:00
|
|
|
t = self.timeout
|
|
|
|
dt = t/retries
|
|
|
|
while t > 0:
|
|
|
|
try:
|
|
|
|
ok = await asyncio.wait_for(
|
|
|
|
self.controllers.active[name].call("ping"), dt)
|
|
|
|
if not ok:
|
|
|
|
raise ValueError("unexcepted ping() response from "
|
|
|
|
"controller `{}`: `{}`".format(name, ok))
|
|
|
|
return ok
|
|
|
|
except asyncio.TimeoutError:
|
|
|
|
t -= dt
|
|
|
|
except (ConnectionAbortedError, ConnectionError,
|
|
|
|
ConnectionRefusedError, ConnectionResetError):
|
|
|
|
await asyncio.sleep(dt)
|
|
|
|
t -= dt
|
|
|
|
raise asyncio.TimeoutError
|
|
|
|
|
2016-01-28 09:45:08 +08:00
|
|
|
def start_controllers(self, *names):
|
|
|
|
fut = asyncio.run_coroutine_threadsafe(self._start(*names), self.loop)
|
|
|
|
fut.result()
|
2015-07-05 11:44:28 +08:00
|
|
|
|
|
|
|
|
2015-06-26 12:19:11 +08:00
|
|
|
@unittest.skipUnless(artiq_root, "no ARTIQ_ROOT")
|
|
|
|
class ExperimentCase(unittest.TestCase):
|
|
|
|
def setUp(self):
|
2015-10-12 19:20:04 +08:00
|
|
|
self.device_db = DeviceDB(os.path.join(artiq_root, "device_db.pyon"))
|
2016-01-28 05:24:32 +08:00
|
|
|
self.dataset_db = DatasetDB(
|
|
|
|
os.path.join(artiq_root, "dataset_db.pyon"))
|
|
|
|
self.device_mgr = DeviceManager(
|
|
|
|
self.device_db, virtual_devices={"scheduler": DummyScheduler()})
|
2015-10-12 19:20:04 +08:00
|
|
|
self.dataset_mgr = DatasetManager(self.dataset_db)
|
2015-06-26 12:19:11 +08:00
|
|
|
|
2015-08-28 18:24:57 +08:00
|
|
|
def create(self, cls, **kwargs):
|
|
|
|
try:
|
2015-10-13 19:57:19 +08:00
|
|
|
exp = cls(self.device_mgr, self.dataset_mgr, **kwargs)
|
2015-08-28 18:24:57 +08:00
|
|
|
exp.prepare()
|
|
|
|
return exp
|
|
|
|
except KeyError as e:
|
|
|
|
# skip if ddb does not match requirements
|
|
|
|
raise unittest.SkipTest(*e.args)
|
|
|
|
|
|
|
|
def execute(self, cls, *args, **kwargs):
|
2015-06-26 12:19:11 +08:00
|
|
|
expid = {
|
|
|
|
"file": sys.modules[cls.__module__].__file__,
|
2015-07-15 17:08:12 +08:00
|
|
|
"class_name": cls.__name__,
|
2015-06-26 12:19:11 +08:00
|
|
|
"arguments": kwargs
|
|
|
|
}
|
2015-10-12 19:20:04 +08:00
|
|
|
self.device_mgr.virtual_devices["scheduler"].expid = expid
|
2015-06-26 12:19:11 +08:00
|
|
|
try:
|
2015-08-28 18:24:57 +08:00
|
|
|
exp = self.create(cls, **kwargs)
|
2015-06-26 12:19:11 +08:00
|
|
|
exp.run()
|
|
|
|
exp.analyze()
|
2015-07-05 10:05:11 +08:00
|
|
|
return exp
|
2015-09-01 12:52:39 +08:00
|
|
|
except CompileError as error:
|
|
|
|
# Reduce amount of text on terminal.
|
|
|
|
raise error from None
|
2015-06-26 12:19:11 +08:00
|
|
|
finally:
|
2015-10-12 19:20:04 +08:00
|
|
|
self.device_mgr.close_devices()
|