forked from M-Labs/artiq
Add test/release notes for command-less controllers
See eaa1b44b00
for the actual change.
This commit is contained in:
parent
eaa1b44b00
commit
ef934ad958
|
@ -13,12 +13,16 @@ ARTIQ-5
|
||||||
:class:`~artiq.coredevice.ad9914.AD9914` phase reference timestamp parameters
|
:class:`~artiq.coredevice.ad9914.AD9914` phase reference timestamp parameters
|
||||||
have been renamed to ``ref_time_mu`` for consistency, as they are in machine
|
have been renamed to ``ref_time_mu`` for consistency, as they are in machine
|
||||||
units.
|
units.
|
||||||
* :func:`~artiq.tools.verbosity_args` renamed to :func:`~artiq.tools.add_common_args`. New feature: adds an option to print the ARTIQ version.
|
* :func:`~artiq.tools.verbosity_args` has been renamed to
|
||||||
|
:func:`~artiq.tools.add_common_args`, and now adds a ``--version`` flag.
|
||||||
* A gateware-level input edge counter has been added, which offers higher
|
* A gateware-level input edge counter has been added, which offers higher
|
||||||
throughput and increased flexibility over the usual TTL input PHYs where
|
throughput and increased flexibility over the usual TTL input PHYs where
|
||||||
edge timestamps are not required. See :mod:`artiq.coredevice.edge_counter` for
|
edge timestamps are not required. See :mod:`artiq.coredevice.edge_counter` for
|
||||||
the core device driver and :mod:`artiq.gateware.rtio.phy.edge_counter`/
|
the core device driver and :mod:`artiq.gateware.rtio.phy.edge_counter`/
|
||||||
:meth:`artiq.gateware.eem.DIO.add_std` for the gateware components.
|
:meth:`artiq.gateware.eem.DIO.add_std` for the gateware components.
|
||||||
|
* The controller manager now ignores device database entries without the
|
||||||
|
``"command"`` key set to facilitate sharing of devices between multiple
|
||||||
|
masters.
|
||||||
|
|
||||||
|
|
||||||
ARTIQ-4
|
ARTIQ-4
|
||||||
|
|
|
@ -6,6 +6,7 @@ import asyncio
|
||||||
|
|
||||||
from artiq.devices.ctlmgr import Controllers
|
from artiq.devices.ctlmgr import Controllers
|
||||||
from artiq.protocols.pc_rpc import AsyncioClient
|
from artiq.protocols.pc_rpc import AsyncioClient
|
||||||
|
from artiq.tools import expect_no_log_messages
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -70,3 +71,13 @@ class ControllerCase(unittest.TestCase):
|
||||||
await remote.ping()
|
await remote.ping()
|
||||||
|
|
||||||
self.loop.run_until_complete(test())
|
self.loop.run_until_complete(test())
|
||||||
|
|
||||||
|
def test_no_command_controller(self):
|
||||||
|
entry = {
|
||||||
|
"type": "controller",
|
||||||
|
"host": "::1",
|
||||||
|
"port": 3253
|
||||||
|
}
|
||||||
|
with expect_no_log_messages(logging.ERROR):
|
||||||
|
self.controllers["lda_sim"] = entry
|
||||||
|
self.assertTrue(self.controllers.queue.empty())
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import atexit
|
import atexit
|
||||||
import collections
|
import collections
|
||||||
|
import contextlib
|
||||||
import importlib.machinery
|
import importlib.machinery
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
@ -16,6 +17,7 @@ from artiq.protocols import pyon
|
||||||
|
|
||||||
__all__ = ["parse_arguments", "elide", "short_format", "file_import",
|
__all__ = ["parse_arguments", "elide", "short_format", "file_import",
|
||||||
"get_experiment", "add_common_args", "simple_network_args",
|
"get_experiment", "add_common_args", "simple_network_args",
|
||||||
|
"UnexpectedLogMessageError", "expect_no_log_messages",
|
||||||
"multiline_log_config", "init_logger", "bind_address_from_args",
|
"multiline_log_config", "init_logger", "bind_address_from_args",
|
||||||
"atexit_register_coroutine", "exc_to_warning",
|
"atexit_register_coroutine", "exc_to_warning",
|
||||||
"asyncio_wait_or_cancel", "TaskObject", "Condition",
|
"asyncio_wait_or_cancel", "TaskObject", "Condition",
|
||||||
|
@ -142,6 +144,36 @@ def simple_network_args(parser, default_port):
|
||||||
help=h)
|
help=h)
|
||||||
|
|
||||||
|
|
||||||
|
class UnexpectedLogMessageError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FailingLogHandler(logging.Handler):
|
||||||
|
def emit(self, record):
|
||||||
|
raise UnexpectedLogMessageError("Unexpected log message: '{}'".format(
|
||||||
|
record.getMessage()))
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def expect_no_log_messages(level, logger=None):
|
||||||
|
"""Raise an UnexpectedLogMessageError if a log message of the given level
|
||||||
|
(or above) is emitted while the context is active.
|
||||||
|
|
||||||
|
Example: ::
|
||||||
|
|
||||||
|
with expect_no_log_messages(logging.ERROR):
|
||||||
|
do_stuff_that_should_not_log_errors()
|
||||||
|
"""
|
||||||
|
if logger is None:
|
||||||
|
logger = logging.getLogger()
|
||||||
|
handler = FailingLogHandler(level)
|
||||||
|
logger.addHandler(handler)
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
logger.removeHandler(handler)
|
||||||
|
|
||||||
|
|
||||||
class MultilineFormatter(logging.Formatter):
|
class MultilineFormatter(logging.Formatter):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
logging.Formatter.__init__(
|
logging.Formatter.__init__(
|
||||||
|
|
Loading…
Reference in New Issue