def test_listener_waits_for_notifier_to_complete(self): listener = PostgresListenerService() yield listener.startService() try: self.assertTrue(listener.notifier.running) finally: yield listener.stopService() self.assertFalse(listener.notifier.running)
def test_register_adds_channel_and_handler(self): listener = PostgresListenerService() channel = factory.make_name("channel", sep="_").lower() listener.register(channel, sentinel.handler) yield listener.startService() try: yield listener.channelRegistrarDone self.assertEqual([sentinel.handler], listener.listeners[channel]) self.assertIn(channel, listener.registeredChannels) finally: yield listener.stopService()
def test__calls_handler_on_notification(self): listener = PostgresListenerService() dv = DeferredValue() listener.register("machine", lambda *args: dv.set(args)) yield listener.startService() try: yield deferToDatabase(self.send_notification, "machine_create", 1) yield dv.get(timeout=2) self.assertEqual(('create', '1'), dv.value) finally: yield listener.stopService()
def test_calls_handler_on_notification(self): listener = PostgresListenerService() listener.HANDLE_NOTIFY_DELAY = listener.CHANNEL_REGISTRAR_DELAY = 0 dv = DeferredValue() listener.register("machine", lambda *args: dv.set(args)) yield listener.startService() yield listener.channelRegistrarDone try: yield deferToDatabase(self.send_notification, "machine_create", 1) yield dv.get(timeout=2) self.assertEqual(("create", "1"), dv.value) finally: yield listener.stopService()
def test__handles_missing_notify_system_listener_on_notification(self): listener = PostgresListenerService() # Change notifications to a frozenset. This makes sure that # the system message does not go into the queue. Instead if should # call the handler directly in `doRead`. listener.notifications = frozenset() yield listener.startService() yield deferToDatabase(listener.registerChannel, "sys_test") try: yield deferToDatabase(self.send_notification, "sys_test", 1) self.assertFalse("sys_test" in listener.listeners) finally: yield listener.stopService()
def test__calls_handler_on_notification_with_delayed_registration(self): listener = PostgresListenerService() dv = DeferredValue() yield listener.startService() try: # Register after the service has been started. The handler should # still be called. listener.register("machine", lambda *args: dv.set(args)) yield deferToDatabase(self.send_notification, "machine_create", 1) yield dv.get(timeout=2) self.assertEqual(('create', '1'), dv.value) finally: yield listener.stopService()
def test_event_on_connection(self): listener = PostgresListenerService() start_calls = [] stop_calls = [] listener.events.connected.registerHandler( lambda: start_calls.append(True)) listener.events.disconnected.registerHandler( lambda reason: stop_calls.append(reason)) yield listener.startService() self.assertEqual(len(start_calls), 1) yield listener.stopService() self.assertEqual(len(stop_calls), 1) [failure] = stop_calls self.assertIsInstance(failure.value, error.ConnectionDone)
def test_unregister_calls_unregisterChannel_when_connected(self): listener = PostgresListenerService() channel = factory.make_name("channel", sep="_").lower() listener.register(channel, sentinel.handler) yield listener.startService() try: yield listener.channelRegistrarDone self.assertIn(channel, listener.registeredChannels) listener.unregister(channel, sentinel.handler) yield listener.channelRegistrarDone finally: yield listener.stopService() self.assertNotIn(channel, listener.registeredChannels)
def test__calls_system_handler_on_notification(self): listener = PostgresListenerService() # Change notifications to a frozenset. This makes sure that # the system message does not go into the queue. Instead if should # call the handler directly in `doRead`. listener.notifications = frozenset() dv = DeferredValue() listener.register("sys_test", lambda *args: dv.set(args)) yield listener.startService() try: yield deferToDatabase(self.send_notification, "sys_test", 1) yield dv.get(timeout=2) self.assertEqual(("sys_test", "1"), dv.value) finally: yield listener.stopService()
def test__tryConnection_reregisters_channels(self): listener = PostgresListenerService() handler = object() listener.register("channel", handler) yield listener.startService() yield listener.channelRegistrarDone listener.registerChannel = Mock() yield listener.stopService() yield listener.tryConnection() yield listener.channelRegistrarDone try: self.assertEqual([call("channel")], listener.registerChannel.mock_calls) self.assertEqual({"channel": [handler]}, listener.listeners) self.assertEqual(set(["channel"]), listener.registeredChannels) finally: yield listener.stopService()
def test_startService_registers_with_postgres_listener(self): regionProcessId = random.randint(0, 100) ipcWorker = IPCWorkerService(sentinel.reactor) ipcWorker.processId.set(regionProcessId) listener = PostgresListenerService() yield listener.startService() service = RackControllerService(ipcWorker, listener) yield service.startService() yield listener.channelRegistrarDone sys_channel = f"sys_core_{regionProcessId}" self.assertIn(sys_channel, listener.listeners) self.assertIn(sys_channel, listener.registeredChannels) self.assertIn(service.coreHandler, listener.listeners[sys_channel]) self.assertEqual(regionProcessId, service.processId) yield listener.stopService()
def test_listener_ignores_ENOENT_when_removing_itself_from_reactor(self): listener = PostgresListenerService() self.patch(reactor, "addReader") self.patch(reactor, "removeReader") # removeReader() is going to have a nasty accident. enoent = IOError("ENOENT") enoent.errno = errno.ENOENT reactor.removeReader.side_effect = enoent # The listener starts and stops without issue. yield listener.startService() yield listener.stopService() # addReader() and removeReader() were both called. self.assertThat(reactor.addReader, MockCalledOnceWith(listener)) self.assertThat(reactor.removeReader, MockCalledOnceWith(listener))
def test_stopping_cancels_start(self): listener = PostgresListenerService() # Start then stop immediately, without waiting for start to complete. starting = listener.startService() starting_spy = DeferredValue() starting_spy.observe(starting) stopping = listener.stopService() # Both `starting` and `stopping` have callbacks yet to fire. self.assertThat(starting.callbacks, Not(Equals([]))) self.assertThat(stopping.callbacks, Not(Equals([]))) # Wait for the listener to stop. yield stopping # Neither `starting` nor `stopping` have callbacks. This is because # `stopping` chained itself onto the end of `starting`. self.assertThat(starting.callbacks, Equals([])) self.assertThat(stopping.callbacks, Equals([])) # Confirmation that `starting` was cancelled. with ExpectedException(CancelledError): yield starting_spy.get()
def test_multiple_starts_return_same_Deferred(self): listener = PostgresListenerService() self.assertThat(listener.startService(), Is(listener.startService())) return listener.stopService()