Sanitize process class hierarchy.

Also deflake process related tests.
looper
Ben Niemann 2017-10-07 16:31:02 +02:00
parent 5d91a0112a
commit ff6f8151c9
19 changed files with 165 additions and 281 deletions

View File

@ -100,13 +100,17 @@ def main(argv):
print(' '.join(subargv))
os.execv(subargv[0], subargv)
logging.basicConfig()
logging.getLogger().setLevel({
'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL,
root_logger = logging.getLogger()
for handler in root_logger.handlers:
root_logger.removeHandler(handler)
logging.basicConfig(
format='%(levelname)-8s:%(process)5s:%(thread)08x:%(name)s: %(message)s',
level={
'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL,
}[args.log_level])
if args.rebuild:

View File

@ -68,30 +68,13 @@ class AudioProcClient(
self.window.handle_pipeline_status(status)
class AudioProcProcessImpl(object):
def __init__(self, event_loop):
super().__init__()
self.event_loop = event_loop
self.server = ipc.Server(self.event_loop, 'process')
async def setup(self):
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
class AudioProcProcess(
audioproc_process.AudioProcProcessMixin, AudioProcProcessImpl):
pass
class AudioPlaygroundApp(QtWidgets.QApplication):
def __init__(self):
super().__init__(['noisipg'])
async def main(self, event_loop):
audioproc = AudioProcProcess(event_loop)
audioproc = audioproc_process.AudioProcProcess(
name='audioproc', event_loop=event_loop, manager=None)
await audioproc.setup()
try:
window = AudioPlaygroundWindow(event_loop)

View File

@ -52,24 +52,6 @@ class TestClient(audioproc_client.AudioProcClientMixin, TestClientImpl):
pass
class TestAudioProcProcessImpl(object):
def __init__(self, event_loop):
super().__init__()
self.event_loop = event_loop
self.server = ipc.Server(self.event_loop, 'audioproc')
async def setup(self):
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
class TestAudioProcProcess(
audioproc_process.AudioProcProcessMixin, TestAudioProcProcessImpl):
pass
class ProxyTest(asynctest.TestCase):
async def setUp(self):
self.passthru_description = node_db.ProcessorDescription(
@ -89,7 +71,8 @@ class ProxyTest(asynctest.TestCase):
direction=node_db.PortDirection.Output),
])
self.audioproc_process = TestAudioProcProcess(self.loop)
self.audioproc_process = audioproc_process.AudioProcProcess(
name='audioproc', event_loop=self.loop, manager=None)
await self.audioproc_process.setup()
self.audioproc_task = self.loop.create_task(
self.audioproc_process.run())

View File

@ -99,9 +99,9 @@ class Session(object):
self.publish_mutation(self.pending_mutations.pop(0))
class AudioProcProcessMixin(object):
def __init__(self, *args, shm=None, profile_path=None, **kwargs):
super().__init__(*args, **kwargs)
class AudioProcProcess(core.ProcessBase):
def __init__(self, *, shm=None, profile_path=None, **kwargs):
super().__init__(**kwargs)
self.shm_name = shm
self.profile_path = profile_path
self.shm = None
@ -382,5 +382,5 @@ class AudioProcProcessMixin(object):
self.__vm.dump()
class AudioProcProcess(AudioProcProcessMixin, core.ProcessImpl):
class AudioProcSubprocess(core.SubprocessMixin, AudioProcProcess):
pass

View File

@ -33,7 +33,9 @@ from .model_base import (
DeferredReference,
)
from .process_manager import (
ProcessManager, ProcessImpl
ProcessManager,
ProcessBase,
SubprocessMixin,
)
from .callbacks import (
CallbackRegistry,

View File

@ -244,9 +244,11 @@ class ChildCollector(object):
self.__stop = threading.Event()
self.__thread = threading.Thread(target=self.__main)
self.__thread.start()
logger.info("Started ChildCollector thread 0x%08x", self.__thread.ident)
def cleanup(self):
if self.__thread is not None:
logger.info("Stopping ChildCollector thread 0x%08x", self.__thread.ident)
self.__stop.set()
self.__thread.join()
self.__thread = None
@ -331,15 +333,19 @@ class ChildCollector(object):
class ProcessManager(object):
def __init__(self, event_loop):
def __init__(self, event_loop, collect_stats=True):
self._event_loop = event_loop
self._processes = {}
self._sigchld_received = asyncio.Event()
self._server = ipc.Server(event_loop, 'manager')
self._stats_collector = stats.Collector()
self._child_collector = ChildCollector(
self._stats_collector)
if collect_stats:
self._stats_collector = stats.Collector()
self._child_collector = ChildCollector(self._stats_collector)
else:
self._stats_collector = None
self._child_collector = None
@property
def server(self):
@ -356,10 +362,13 @@ class ProcessManager(object):
'STATS_FETCH', self.handle_stats_fetch)
await self._server.setup()
self._child_collector.setup()
if self._child_collector is not None:
self._child_collector.setup()
async def cleanup(self):
self._child_collector.cleanup()
if self._child_collector is not None:
self._child_collector.cleanup()
await self.terminate_all_children()
await self._server.cleanup()
@ -420,8 +429,8 @@ class ProcessManager(object):
for sig in signal.Signals:
self._event_loop.remove_signal_handler(sig)
# Clear all stats inherited from the manager process.
stats.registry.clear()
# Create a new stats registry for this process.
stats.registry = stats.Registry()
# Close the "other ends" of the pipes.
os.close(request_out)
@ -494,7 +503,7 @@ class ProcessManager(object):
proc.pid = pid
proc.create_loggers()
proc.logger.info("Created new subprocess.")
proc.logger.info("Created new subprocess '%s' (%s).", name, cls)
await proc.setup_std_handlers(
self._event_loop, stdout_in, stderr_in, logger_in)
@ -505,7 +514,10 @@ class ProcessManager(object):
stub_address = await child_connection.read_async(self._event_loop)
self._child_collector.add_child(pid, child_connection)
if self._child_collector is not None:
self._child_collector.add_child(pid, child_connection)
else:
child_connection.close()
proc.address = stub_address.decode('utf-8')
logger.info(
@ -575,13 +587,18 @@ class ProcessManager(object):
dead_children.add(pid)
for pid in dead_children:
self._child_collector.remove_child(pid)
if self._child_collector is not None:
self._child_collector.remove_child(pid)
del self._processes[pid]
def handle_stats_list(self):
if self._stats_collector is None:
return RuntimeError("Stats collection not enabled.")
return self._stats_collector.list_stats()
def handle_stats_fetch(self, expressions):
if self._stats_collector is None:
return RuntimeError("Stats collection not enabled.")
return self._stats_collector.fetch_stats(expressions)
@ -596,10 +613,11 @@ class ChildConnectionHandler(object):
self.__stop = eventfd.EventFD()
self.__thread = threading.Thread(target=self.__main)
self.__thread.start()
logger.info("Started ChildConnectionHandler thread 0x%08x", self.__thread.ident)
def cleanup(self):
if self.__thread is not None:
logger.info("Stopping ChildConnectionHandler...")
logger.info("Stopping ChildConnectionHandler thread 0x%08x...", self.__thread.ident)
self.__stop.set()
self.__thread.join()
self.__thread = None
@ -633,16 +651,32 @@ class ChildConnectionHandler(object):
logger.info("ChildConnectionHandler stopped.")
class ProcessImpl(object):
def __init__(self, name, manager_address):
class ProcessBase(object):
def __init__(self, *, name, manager, event_loop):
self.name = name
self.manager_address = manager_address
self.event_loop = None
self.pid = os.getpid()
self.manager = None
self.manager = manager
self.event_loop = event_loop
self.server = None
async def setup(self):
self.server = ipc.Server(self.event_loop, self.name)
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
self.server = None
async def run(self):
raise NotImplementedError(type(self).__name__)
class SubprocessMixin(object):
def __init__(self, *, manager_address, **kwargs):
super().__init__(manager=None, event_loop=None, **kwargs)
self.manager_address = manager_address
self.pid = os.getpid()
def create_event_loop(self):
return asyncio.new_event_loop()
@ -664,53 +698,42 @@ class ProcessImpl(object):
self.main_async(child_connection, *args, **kwargs))
finally:
logger.info("Closing event loop...")
self.event_loop.stop()
self.event_loop.run_until_complete(
asyncio.gather(*asyncio.Task.all_tasks(self.event_loop)))
self.event_loop.stop()
self.event_loop.close()
logger.info("Event loop closed.")
async def main_async(self, child_connection, *args, **kwargs):
self.manager = ManagerStub(self.event_loop, self.manager_address)
async with self.manager:
self.server = ipc.Server(self.event_loop, self.name)
async with self.server:
try:
logger.info("Setting up process.")
await self.setup()
stub_address = self.server.address.encode('utf-8')
child_connection.write(stub_address)
child_connection_handler = ChildConnectionHandler(child_connection)
child_connection_handler.setup()
try:
logger.info("Setting up process.")
await self.setup()
logger.info("Entering run method.")
return await self.run(*args, **kwargs)
stub_address = self.server.address.encode('utf-8')
child_connection.write(stub_address)
child_connection_handler = ChildConnectionHandler(child_connection)
child_connection_handler.setup()
try:
logger.info("Entering run method.")
return await self.run(*args, **kwargs)
except Exception as exc:
logger.error(
"Unhandled exception in process %s:\n%s",
self.name, traceback.format_exc())
raise
finally:
logger.info("Closing child connection...")
child_connection_handler.cleanup()
child_connection.close()
logger.info("Child connection closed.")
except Exception as exc:
logger.error(
"Unhandled exception in process %s:\n%s",
self.name, traceback.format_exc())
raise
finally:
await self.cleanup()
logger.info("Closing child connection...")
child_connection_handler.cleanup()
child_connection.close()
logger.info("Child connection closed.")
async def setup(self):
pass
async def cleanup(self):
pass
async def run(self):
raise NotImplementedError("Subclass must override run")
finally:
await self.cleanup()
class SetPIDHandler(logging.Handler):

View File

@ -33,74 +33,69 @@ from . import process_manager
class ProcessManagerTest(asynctest.TestCase):
@unittest.skip("FIXME: test hangs infinitely.")
async def test_simple(self):
class Child(process_manager.ProcessImpl):
def __init__(self, foo, **kwargs):
class Child(process_manager.SubprocessMixin, process_manager.ProcessBase):
def __init__(self, *, foo, **kwargs):
super().__init__(**kwargs)
assert foo == 'bar'
async def run(self):
pass
async with process_manager.ProcessManager(self.loop) as mgr:
async with process_manager.ProcessManager(self.loop, collect_stats=False) as mgr:
proc = await mgr.start_process('test', Child, foo='bar')
await proc.wait()
self.assertEqual(proc.returncode, 0)
@unittest.skip("FIXME: test hangs infinitely.")
async def test_child_fails(self):
class Child(process_manager.ProcessImpl):
class Child(process_manager.SubprocessMixin, process_manager.ProcessBase):
async def run(self):
sys.exit(2)
os._exit(2)
async with process_manager.ProcessManager(self.loop) as mgr:
async with process_manager.ProcessManager(self.loop, collect_stats=False) as mgr:
proc = await mgr.start_process('test', Child)
await proc.wait()
self.assertEqual(proc.returncode, 2)
@unittest.skip("FIXME: test hangs infinitely.")
async def test_child_killed(self):
class Child(process_manager.ProcessImpl):
class Child(process_manager.SubprocessMixin, process_manager.ProcessBase):
async def run(self):
os.kill(self.pid, signal.SIGKILL)
async with process_manager.ProcessManager(self.loop) as mgr:
async with process_manager.ProcessManager(self.loop, collect_stats=False) as mgr:
proc = await mgr.start_process('test', Child)
await proc.wait()
self.assertEqual(proc.returncode, 1)
self.assertEqual(proc.signal, signal.SIGKILL)
@unittest.skip("FIXME: test hangs infinitely.")
async def test_left_over(self):
class Child(process_manager.ProcessImpl):
class Child(process_manager.SubprocessMixin, process_manager.ProcessBase):
async def run(self):
while True:
await asyncio.sleep(1)
async with process_manager.ProcessManager(self.loop) as mgr:
async with process_manager.ProcessManager(self.loop, collect_stats=False) as mgr:
stub = await mgr.start_process('test', Child)
@unittest.skip("FIXME: test hangs infinitely.")
async def test_left_over_sigterm_fails(self):
class Child(process_manager.ProcessImpl):
class Child(process_manager.SubprocessMixin, process_manager.ProcessBase):
async def run(self):
signal.signal(signal.SIGTERM, signal.SIG_IGN)
while True:
await asyncio.sleep(1)
async with process_manager.ProcessManager(self.loop) as mgr:
async with process_manager.ProcessManager(self.loop, collect_stats=False) as mgr:
stub = await mgr.start_process('test', Child)
await mgr.terminate_all_children(timeout=0.2)
async def test_capture_stdout(self):
class Child(process_manager.ProcessImpl):
class Child(process_manager.SubprocessMixin, process_manager.ProcessBase):
async def run(self):
for i in range(10):
print(i)
sys.stderr.write('goo')
async with process_manager.ProcessManager(self.loop) as mgr:
async with process_manager.ProcessManager(self.loop, collect_stats=False) as mgr:
proc = await mgr.start_process('test', Child)
await proc.wait()
self.assertEqual(proc.returncode, 0)

View File

@ -99,7 +99,7 @@ class Editor(object):
while True:
next_retry = time.time() + 5
proc = await self.manager.start_process(
'ui', 'noisicaa.ui.ui_process.UIProcess',
'ui', 'noisicaa.ui.ui_process.UISubprocess',
runtime_settings=self.runtime_settings,
paths=self.paths)
await proc.wait()
@ -141,7 +141,7 @@ class Editor(object):
# TODO: keep map of uri->proc, only create processes for new
# URIs.
proc = await self.manager.start_process(
'project', 'noisicaa.music.project_process.ProjectProcess')
'project', 'noisicaa.music.project_process.ProjectSubprocess')
return proc.address
async def handle_create_audioproc_process(self, name, **kwargs):
@ -149,7 +149,7 @@ class Editor(object):
# names.
proc = await self.manager.start_process(
'audioproc<%s>' % name,
'noisicaa.audioproc.audioproc_process.AudioProcProcess',
'noisicaa.audioproc.audioproc_process.AudioProcSubprocess',
**kwargs)
return proc.address
@ -158,7 +158,7 @@ class Editor(object):
if self.node_db_process is None:
self.node_db_process = await self.manager.start_process(
'node_db',
'noisicaa.node_db.process.NodeDBProcess')
'noisicaa.node_db.process.NodeDBSubprocess')
return self.node_db_process.address
@ -167,7 +167,7 @@ class Editor(object):
if self.instrument_db_process is None:
self.instrument_db_process = await self.manager.start_process(
'instrument_db',
'noisicaa.instrument_db.process.InstrumentDBProcess')
'noisicaa.instrument_db.process.InstrumentDBSubprocess')
return self.instrument_db_process.address

View File

@ -51,26 +51,10 @@ class TestClient(client.InstrumentDBClientMixin, TestClientImpl):
pass
class TestProcessImpl(object):
def __init__(self, event_loop):
super().__init__()
self.event_loop = event_loop
self.server = ipc.Server(self.event_loop, 'audioproc')
async def setup(self):
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
class TestProcess(process.InstrumentDBProcessMixin, TestProcessImpl):
pass
class InstrumentDBClientTest(asynctest.TestCase):
async def setUp(self):
self.process = TestProcess(self.loop)
self.process = process.InstrumentDBProcess(
name='instrument_db', event_loop=self.loop, manager=None)
await self.process.setup()
self.process_task = self.loop.create_task(
self.process.run())

View File

@ -80,9 +80,9 @@ class Session(object):
self.pending_mutations.clear()
class InstrumentDBProcessMixin(process_base.InstrumentDBProcessBase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
class InstrumentDBProcess(process_base.InstrumentDBProcessBase):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.sessions = {}
self.db = None
self.search_paths = [
@ -168,5 +168,5 @@ class InstrumentDBProcessMixin(process_base.InstrumentDBProcessBase):
return self.db.start_scan(self.search_paths, True)
class InstrumentDBProcess(InstrumentDBProcessMixin, core.ProcessImpl):
class InstrumentDBSubprocess(core.SubprocessMixin, InstrumentDBProcess):
pass

View File

@ -20,7 +20,10 @@
#
# @end:license
class InstrumentDBProcessBase(object):
from noisicaa import core
class InstrumentDBProcessBase(core.ProcessBase):
async def setup(self):
await super().setup()

View File

@ -57,24 +57,6 @@ from . import project_client
logger = logging.getLogger(__name__)
class TestAudioProcProcessImpl(object):
def __init__(self, event_loop, name):
super().__init__()
self.event_loop = event_loop
self.server = ipc.Server(self.event_loop, name)
async def setup(self):
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
class TestAudioProcProcess(
audioproc_process.AudioProcProcessMixin, TestAudioProcProcessImpl):
pass
class TestAudioProcClientImpl(object):
def __init__(self, event_loop, name):
super().__init__()
@ -137,7 +119,8 @@ class PlayerTest(asynctest.TestCase):
self.callback_server = CallbackServer(self.loop)
await self.callback_server.setup()
self.audioproc_server_main = TestAudioProcProcess(self.loop, 'main_process')
self.audioproc_server_main = audioproc_process.AudioProcProcess(
name='main_process', event_loop=self.loop, manager=None)
await self.audioproc_server_main.setup()
self.audioproc_server_main_task = self.loop.create_task(
self.audioproc_server_main.run())
@ -151,8 +134,8 @@ class PlayerTest(asynctest.TestCase):
profile_path = None
if constants.TEST_OPTS.ENABLE_PROFILER:
profile_path = os.path.join(tempfile.gettempdir(), self.id() + '.prof')
self.audioproc_server_player = TestAudioProcProcess(
self.loop, 'player_process',
self.audioproc_server_player = audioproc_process.AudioProcProcess(
name='player_process', event_loop=self.loop, manager=None,
profile_path=profile_path)
await self.audioproc_server_player.setup()
self.audioproc_server_player_task = self.loop.create_task(

View File

@ -55,25 +55,6 @@ class TestClient(project_client.ProjectClientMixin, TestClientImpl):
pass
class TestProjectProcessImpl(object):
def __init__(self, event_loop, manager):
super().__init__()
self.event_loop = event_loop
self.manager = manager
self.server = ipc.Server(self.event_loop, 'project')
async def setup(self):
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
class TestProjectProcess(
project_process.ProjectProcessMixin, TestProjectProcessImpl):
pass
class AsyncSetupBase():
async def setup(self):
pass
@ -81,20 +62,7 @@ class AsyncSetupBase():
async def cleanup(self):
pass
class TestNodeDBProcess(node_db.NodeDBProcessBase, AsyncSetupBase):
def __init__(self, event_loop):
super().__init__()
self.event_loop = event_loop
self.server = ipc.Server(self.event_loop, 'node_db')
async def setup(self):
await super().setup()
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
await super().cleanup()
class TestNodeDBProcess(node_db.NodeDBProcessBase):
def handle_start_session(self, client_address, flags):
return '123'
@ -104,7 +72,8 @@ class TestNodeDBProcess(node_db.NodeDBProcessBase, AsyncSetupBase):
class ProxyTest(asynctest.TestCase):
async def setUp(self):
self.node_db_process = TestNodeDBProcess(self.loop)
self.node_db_process = TestNodeDBProcess(
name='node_db', event_loop=self.loop, manager=None)
await self.node_db_process.setup()
self.manager = mock.Mock()
@ -113,8 +82,10 @@ class ProxyTest(asynctest.TestCase):
return self.node_db_process.server.address
self.manager.call.side_effect = mock_call
self.project_process = TestProjectProcess(self.loop, self.manager)
self.project_process = project_process.ProjectProcess(
name='project', manager=self.manager, event_loop=self.loop)
await self.project_process.setup()
self.client = TestClient(self.loop)
self.client.cls_map = model.cls_map
await self.client.setup()

View File

@ -186,9 +186,9 @@ class NodeDBClient(node_db.NodeDBClientMixin, NodeDBClientImpl):
pass
class ProjectProcessMixin(object):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
class ProjectProcess(core.ProcessBase):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._shutting_down = None
@ -488,5 +488,5 @@ class ProjectProcessMixin(object):
session.set_values(data, from_client=True)
class ProjectProcess(ProjectProcessMixin, core.ProcessImpl):
class ProjectSubprocess(core.SubprocessMixin, ProjectProcess):
pass

View File

@ -51,26 +51,10 @@ class TestClient(client.NodeDBClientMixin, TestClientImpl):
pass
class TestProcessImpl(object):
def __init__(self, event_loop):
super().__init__()
self.event_loop = event_loop
self.server = ipc.Server(self.event_loop, 'audioproc')
async def setup(self):
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
class TestProcess(process.NodeDBProcessMixin, TestProcessImpl):
pass
class NodeDBClientTest(asynctest.TestCase):
async def setUp(self):
self.process = TestProcess(self.loop)
self.process = process.NodeDBProcess(
name='node_db', event_loop=self.loop, manager=None)
await self.process.setup()
self.process_task = self.loop.create_task(
self.process.run())

View File

@ -54,9 +54,9 @@ class Session(object):
await self.callback_stub.call('NODEDB_MUTATION', mutation)
class NodeDBProcessMixin(process_base.NodeDBProcessBase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
class NodeDBProcess(process_base.NodeDBProcessBase):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.sessions = {}
self.db = db.NodeDB()
@ -117,5 +117,5 @@ class NodeDBProcessMixin(process_base.NodeDBProcessBase):
return self.db.start_scan()
class NodeDBProcess(NodeDBProcessMixin, core.ProcessImpl):
class NodeDBSubprocess(core.SubprocessMixin, NodeDBProcess):
pass

View File

@ -20,7 +20,10 @@
#
# @end:license
class NodeDBProcessBase(object):
from noisicaa import core
class NodeDBProcessBase(core.ProcessBase):
async def setup(self):
await super().setup()

View File

@ -34,8 +34,8 @@ from . import editor_app
logger = logging.getLogger(__name__)
class UIProcessMixin(object):
def __init__(self, runtime_settings, paths, **kwargs):
class UISubprocess(core.SubprocessMixin, core.ProcessBase):
def __init__(self, *, runtime_settings, paths, **kwargs):
super().__init__(**kwargs)
self.app = self.create_app(self, runtime_settings, paths)
@ -69,7 +69,3 @@ class UIProcessMixin(object):
def handle_signal(self, sig):
logger.info("%s received.", sig.name)
self.quit(0)
class UIProcess(UIProcessMixin, core.ProcessImpl):
pass

View File

@ -30,6 +30,7 @@ import asynctest
from PyQt5.QtCore import Qt
from PyQt5 import QtGui
from noisicaa import core
from noisicaa import instrument_db
from noisicaa import node_db
from noisicaa.core import ipc
@ -139,20 +140,7 @@ class AsyncSetupBase():
pass
class TestNodeDBProcess(node_db.NodeDBProcessBase, AsyncSetupBase):
def __init__(self, event_loop):
super().__init__()
self.event_loop = event_loop
self.server = ipc.Server(self.event_loop, 'node_db')
async def setup(self):
await super().setup()
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
await super().cleanup()
class TestNodeDBProcess(node_db.NodeDBProcessBase):
def handle_start_session(self, client_address, flags):
return '123'
@ -163,20 +151,7 @@ class TestNodeDBProcess(node_db.NodeDBProcessBase, AsyncSetupBase):
pass
class TestInstrumentDBProcess(instrument_db.InstrumentDBProcessBase, AsyncSetupBase):
def __init__(self, event_loop):
super().__init__()
self.event_loop = event_loop
self.server = ipc.Server(self.event_loop, 'instrument_db')
async def setup(self):
await super().setup()
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
await super().cleanup()
class TestInstrumentDBProcess(instrument_db.InstrumentDBProcessBase):
def handle_start_session(self, client_address, flags):
return '123'
@ -187,18 +162,10 @@ class TestInstrumentDBProcess(instrument_db.InstrumentDBProcessBase, AsyncSetupB
pass
class MockProcess(object):
def __init__(self, event_loop, manager):
self.event_loop = event_loop
self.manager = manager
class MockProcess(core.ProcessBase):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.project = None
self.server = ipc.Server(self.event_loop, 'ui')
async def setup(self):
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
class MockApp(BaseEditorApp):
@ -221,10 +188,12 @@ class UITest(asynctest.TestCase):
app = None
async def setUp(self):
self.node_db_process = TestNodeDBProcess(self.loop)
self.node_db_process = TestNodeDBProcess(
name='node_db', event_loop=self.loop, manager=None)
await self.node_db_process.setup()
self.instrument_db_process = TestInstrumentDBProcess(self.loop)
self.instrument_db_process = TestInstrumentDBProcess(
name='instrument_db', event_loop=self.loop, manager=None)
await self.instrument_db_process.setup()
self.manager = mock.Mock()
@ -238,7 +207,8 @@ class UITest(asynctest.TestCase):
self.manager.call.side_effect = mock_call
self.process = MockProcess(self.loop, self.manager)
self.process = MockProcess(
name='ui', event_loop=self.loop, manager=self.manager)
await self.process.setup()
if UITest.app is None: