예제 #1
0
    def test_reap_unknown_pid(self):
        options = DummyOptions()
        options.waitpid_return = 2, 0  # pid, status
        pconfig = DummyPConfig(options, 'process', 'process', '/bin/process1')
        process = DummyProcess(pconfig)
        process.drained = False
        process.killing = True
        process.laststop = None
        process.waitstatus = None, None
        options.pidhistory = {1: process}
        supervisord = self._makeOne(options)

        supervisord.reap(once=True)
        self.assertEqual(process.finished, None)
        self.assertEqual(options.logger.data[0], 'reaped unknown pid 2')
예제 #2
0
 def test_handle_listener_state_change_acknowledged_gobbles(self):
     options = DummyOptions()
     config = DummyPConfig(options, 'process1', '/bin/process1')
     process = DummyProcess(config)
     from supervisor.dispatchers import EventListenerStates
     dispatcher = self._makeOne(process)
     process.listener_state = EventListenerStates.ACKNOWLEDGED
     dispatcher.state_buffer = 'READY\ngarbage\n'
     self.assertEqual(dispatcher.handle_listener_state_change(), None)
     self.assertEqual(dispatcher.state_buffer, '')
     self.assertEqual(options.logger.data[0],
                      'process1: ACKNOWLEDGED -> READY')
     self.assertEqual(options.logger.data[1],
                      'process1: READY -> UNKNOWN')
     self.assertEqual(process.listener_state, EventListenerStates.UNKNOWN)
예제 #3
0
 def test_handle_read_event_calls_handle_listener_state_change(self):
     options = DummyOptions()
     config = DummyPConfig(options, 'process1', '/bin/process1',
                           stdout_logfile='/tmp/foo')
     process = DummyProcess(config)
     from supervisor.dispatchers import EventListenerStates
     process.listener_state = EventListenerStates.ACKNOWLEDGED
     dispatcher = self._makeOne(process)
     options.readfd_result = dispatcher.READY_FOR_EVENTS_TOKEN
     self.assertEqual(dispatcher.handle_read_event(), None)
     self.assertEqual(process.listener_state, EventListenerStates.READY)
     self.assertEqual(dispatcher.state_buffer, '')
     self.assertEqual(len(dispatcher.childlog.data), 1)
     self.assertEqual(dispatcher.childlog.data[0],
                      dispatcher.READY_FOR_EVENTS_TOKEN)
예제 #4
0
 def test_exit(self):
     options = DummyOptions()
     supervisord = self._makeOne(options)
     pconfig = DummyPConfig(options, 'foo', '/bin/foo',)
     gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
     pgroup = DummyProcessGroup(gconfig)
     L = []
     def callback():
         L.append(1)
     supervisord.process_groups = {'foo': pgroup}
     supervisord.options.mood = SupervisorStates.RESTARTING
     supervisord.options.test = True
     from supervisor.medusa import asyncore_25 as asyncore
     self.assertRaises(asyncore.ExitNow, supervisord.runforever)
     self.assertEqual(pgroup.all_stopped, True)
예제 #5
0
 def test_unregister_writable(self):
     kqueue = DummyKQueue()
     poller = self._makeOne(DummyOptions())
     poller._kqueue = kqueue
     poller.register_writable(7)
     poller.register_readable(8)
     poller.unregister_writable(7)
     poller.unregister_writable(8)
     poller.unregister_writable(100)  # not registered, ignore error
     self.assertEqual(list(poller.writables), [])
     self.assertEqual(list(poller.readables), [8])
     self.assertWriteEventAdded(kqueue.registered_kevents[0], 7)
     self.assertReadEventAdded(kqueue.registered_kevents[1], 8)
     self.assertWriteEventDeleted(kqueue.registered_kevents[2], 7)
     self.assertWriteEventDeleted(kqueue.registered_kevents[3], 8)
    def test_write_fails_silently_if_oserror_during_write(self):
        options = DummyOptions()
        config = DummyPConfig(options, 'cat', 'bin/cat')

        process = DummyProcess(config)
        process.pid = 42
        process.killing = False
        process.write_error = True

        event = DummyEvent()
        event.process = process

        response = 'STDIN:foobar'
        supervisor_twiddler.resulthandler.stdin_write_handler(event, response)
        self.assertEqual(process.stdin_buffer, '')
예제 #7
0
 def test_handle_request(self):
     f = tempfile.NamedTemporaryFile()
     t = f.name
     options = DummyOptions()
     pconfig = DummyPConfig(options, 'foo', 'foo', stdout_logfile=t)
     supervisord = PopulatedDummySupervisor(options, 'foo', pconfig)
     handler = self._makeOne(supervisord)
     request = DummyRequest('/logtail/foo', None, None, None)
     handler.handle_request(request)
     self.assertEqual(request._error, None)
     from supervisor.medusa import http_date
     self.assertEqual(request.headers['Last-Modified'],
                      http_date.build_http_date(os.stat(t)[stat.ST_MTIME]))
     self.assertEqual(request.headers['Content-Type'], 'text/plain')
     self.assertEqual(len(request.producers), 1)
     self.assertEqual(request._done, True)
예제 #8
0
    def test_record_output_does_not_emit_stderr_event_when_disabled(self):
        options = DummyOptions()
        config = DummyPConfig(options, 'process1', '/bin/process1',
                              stderr_events_enabled=False)
        process = DummyProcess(config)
        dispatcher = self._makeOne(process, 'stderr')
        dispatcher.output_buffer = 'hello from stderr'

        L = []
        def doit(event):
            L.append(event)
        from supervisor import events
        events.subscribe(events.EventTypes.PROCESS_LOG_STDERR, doit)
        dispatcher.record_output()

        self.assertEqual(len(L), 0)
예제 #9
0
 def test_record_output_capturemode_string_not_longer_than_token(self):
     # stdout/stderr goes to the process log and the main log,
     # in capturemode, the length of the data needs to be longer
     # than the capture token to make it out.
     options = DummyOptions()
     config = DummyPConfig(options,
                           'process1',
                           '/bin/process1',
                           stdout_logfile='/tmp/foo',
                           stdout_capture_maxbytes=100)
     process = DummyProcess(config)
     dispatcher = self._makeOne(process)
     dispatcher.output_buffer = 'a'
     dispatcher.record_output()
     self.assertEqual(dispatcher.childlog.data, [])
     self.assertEqual(dispatcher.output_buffer, 'a')
예제 #10
0
 def test_record_output_log_non_capturemode(self):
     # stdout/stderr goes to the process log and the main log,
     # in non-capturemode, the data length doesn't matter
     options = DummyOptions()
     from supervisor import loggers
     options.loglevel = loggers.LevelsByName.TRAC
     config = DummyPConfig(options, 'process1', '/bin/process1',
                           stdout_logfile='/tmp/foo')
     process = DummyProcess(config)
     dispatcher = self._makeOne(process)
     dispatcher.output_buffer = 'a'
     dispatcher.record_output()
     self.assertEqual(dispatcher.childlog.data, ['a'])
     self.assertEqual(options.logger.data[0],
          "'process1' stdout output:\na")
     self.assertEqual(dispatcher.output_buffer, '')
예제 #11
0
 def test_exit_delayed(self):
     options = DummyOptions()
     supervisord = self._makeOne(options)
     pconfig = DummyPConfig(options, 'foo', '/bin/foo',)
     process = DummyProcess(pconfig)
     gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
     pgroup = DummyProcessGroup(gconfig)
     pgroup.unstopped_processes = [process]
     L = []
     def callback():
         L.append(1)
     supervisord.process_groups = {'foo': pgroup}
     supervisord.options.mood = SupervisorStates.RESTARTING
     supervisord.options.test = True
     supervisord.runforever()
     self.assertNotEqual(supervisord.lastshutdownreport, 0)
예제 #12
0
    def test_stdout_capturemode_single_buffer(self):
        # mike reported that comm events that took place within a single
        # output buffer were broken 8/20/2007
        from supervisor.events import ProcessCommunicationEvent
        from supervisor.events import subscribe
        events = []

        def doit(event):
            events.append(event)

        subscribe(ProcessCommunicationEvent, doit)
        BEGIN_TOKEN = ProcessCommunicationEvent.BEGIN_TOKEN
        END_TOKEN = ProcessCommunicationEvent.END_TOKEN
        data = BEGIN_TOKEN + 'hello' + END_TOKEN
        options = DummyOptions()
        from supervisor.loggers import getLogger
        options.getLogger = getLogger  # actually use real logger
        logfile = '/tmp/log'
        config = DummyPConfig(options,
                              'process1',
                              '/bin/process1',
                              stdout_logfile=logfile,
                              stdout_capture_maxbytes=1000)
        process = DummyProcess(config)
        dispatcher = self._makeOne(process)

        try:
            dispatcher.output_buffer = data
            dispatcher.record_output()
            self.assertEqual(read_file(logfile), '')
            self.assertEqual(dispatcher.output_buffer, '')
            self.assertEqual(len(events), 1)

            event = events[0]
            from supervisor.events import ProcessCommunicationStdoutEvent
            self.assertEqual(event.__class__, ProcessCommunicationStdoutEvent)
            self.assertEqual(event.process, process)
            self.assertEqual(event.channel, 'stdout')
            self.assertEqual(event.data, 'hello')

        finally:
            try:
                dispatcher.capturelog.close()
                dispatcher.childlog.close()
                os.remove(logfile)
            except (OSError, IOError):
                pass
예제 #13
0
 def _make_http_servers(self, sconfigs):
     options = DummyOptions()
     options.server_configs = sconfigs
     options.rpcinterface_factories = [('dummy',DummyRPCInterfaceFactory,{})]
     supervisord = DummySupervisor()
     from supervisor.http import make_http_servers
     servers = make_http_servers(options, supervisord)
     try:
         for config, s in servers:
             s.close()
             socketfile = config.get('file')
             if socketfile is not None:
                 os.unlink(socketfile)
     finally:
         from asyncore import socket_map
         socket_map.clear()
     return servers
예제 #14
0
    def test_plog_stdout_event(self):
        options = DummyOptions()
        pconfig1 = DummyPConfig(options, 'process1', 'process1',
                                '/bin/process1')
        process1 = DummyProcess(pconfig1)
        from supervisor.events import ProcessLogStdoutEvent

        class DummyGroup:
            config = pconfig1

        process1.group = DummyGroup
        event = ProcessLogStdoutEvent(process1, 1, 'yo')
        headers, payload = self._deserialize(event.payload())
        self.assertEqual(headers['processname'], 'process1', headers)
        self.assertEqual(headers['groupname'], 'process1', headers)
        self.assertEqual(headers['pid'], '1', headers)
        self.assertEqual(payload, 'yo')
예제 #15
0
 def test_handle_listener_state_change_ready_to_unknown(self):
     options = DummyOptions()
     config = DummyPConfig(options, 'process1', '/bin/process1')
     process = DummyProcess(config)
     from supervisor.dispatchers import EventListenerStates
     dispatcher = self._makeOne(process)
     process.listener_state = EventListenerStates.READY
     dispatcher.state_buffer = 'bogus data yo'
     self.assertEqual(dispatcher.handle_listener_state_change(), None)
     self.assertEqual(dispatcher.state_buffer, '')
     self.assertEqual(options.logger.data[0],
                      'process1: READY -> UNKNOWN')
     self.assertEqual(options.logger.data[1],
                      'process1: has entered the UNKNOWN state and will '
                      'no longer receive events, this usually indicates '
                      'the process violated the eventlistener protocol')
     self.assertEqual(process.listener_state, EventListenerStates.UNKNOWN)
예제 #16
0
    def test_pcomm_stderr_event(self):
        options = DummyOptions()
        pconfig1 = DummyPConfig(options, 'process1', 'process1',
                                '/bin/process1')
        process1 = DummyProcess(pconfig1)

        class DummyGroup:
            config = pconfig1

        process1.group = DummyGroup
        from supervisor.events import ProcessCommunicationStderrEvent
        event = ProcessCommunicationStderrEvent(process1, 1, 'yo')
        headers, payload = self._deserialize(str(event))
        self.assertEqual(headers['processname'], 'process1', headers)
        self.assertEqual(headers['groupname'], 'process1', headers)
        self.assertEqual(headers['pid'], '1', headers)
        self.assertEqual(payload, 'yo')
예제 #17
0
 def test_runforever_select_dispatcher_exitnow_via_write(self):
     options = DummyOptions()
     options.poller.result = [], [6]
     supervisord = self._makeOne(options)
     pconfig = DummyPConfig(
         options,
         'foo',
         '/bin/foo',
     )
     gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
     pgroup = DummyProcessGroup(gconfig)
     from supervisor.medusa import asyncore_25 as asyncore
     exitnow = DummyDispatcher(readable=True, error=asyncore.ExitNow)
     pgroup.dispatchers = {6: exitnow}
     supervisord.process_groups = {'foo': pgroup}
     options.test = True
     self.assertRaises(asyncore.ExitNow, supervisord.runforever)
예제 #18
0
 def test_runforever_select_dispatcher_handle_error_via_write(self):
     options = DummyOptions()
     options.poller.result = [], [6]
     supervisord = self._makeOne(options)
     pconfig = DummyPConfig(
         options,
         'foo',
         '/bin/foo',
     )
     gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
     pgroup = DummyProcessGroup(gconfig)
     notimpl = DummyDispatcher(readable=True, error=NotImplementedError)
     pgroup.dispatchers = {6: notimpl}
     supervisord.process_groups = {'foo': pgroup}
     options.test = True
     supervisord.runforever()
     self.assertEqual(notimpl.error_handled, True)
예제 #19
0
    def test_add_process_group_emits_event(self):
        from supervisor import events
        L = []
        def callback(event):
            L.append(1)
        events.subscribe(events.ProcessGroupAddedEvent, callback)
        options = DummyOptions()
        pconfig = DummyPConfig(options, 'foo', '/bin/foo', '/tmp')
        gconfig = DummyPGroupConfig(options, 'foo', pconfigs=[pconfig])
        options.process_group_configs = [gconfig]
        supervisord = self._makeOne(options)

        supervisord.add_process_group(gconfig)

        options.test = True
        supervisord.runforever()
        self.assertEqual(L, [1])
예제 #20
0
    def test_add_process_group(self):
        options = DummyOptions()
        pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
        gconfig = DummyPGroupConfig(options, 'foo', pconfigs=[pconfig])
        options.process_group_configs = [gconfig]
        supervisord = self._makeOne(options)

        self.assertEqual(supervisord.process_groups, {})

        result = supervisord.add_process_group(gconfig)
        self.assertEqual(list(supervisord.process_groups.keys()), ['foo'])
        self.assertTrue(result)

        group = supervisord.process_groups['foo']
        result = supervisord.add_process_group(gconfig)
        self.assertEqual(group, supervisord.process_groups['foo'])
        self.assertTrue(not result)
예제 #21
0
 def test_handle_sigusr2(self):
     options = DummyOptions()
     options._signal = signal.SIGUSR2
     pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
     from supervisor.process import ProcessStates
     process1 = DummyProcess(pconfig1, state=ProcessStates.STOPPING)
     process1.delay = time.time() - 1
     supervisord = self._makeOne(options)
     pconfigs = [DummyPConfig(options, 'foo', 'foo', '/bin/foo')]
     options.process_group_configs = DummyPGroupConfig(
         options, 'foo',
         pconfigs=pconfigs)
     supervisord.handle_signal()
     self.assertEqual(supervisord.options.mood, 1)
     self.assertEqual(options.logs_reopened, True)
     self.assertEqual(options.logger.data[0],
                      'received SIGUSR2 indicating log reopen request')
예제 #22
0
 def test_runforever_poll_dispatchers(self):
     options = DummyOptions()
     options.poller.result = [6], [7, 8]
     supervisord = self._makeOne(options)
     pconfig = DummyPConfig(options, 'foo', '/bin/foo',)
     gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
     pgroup = DummyProcessGroup(gconfig)
     readable = DummyDispatcher(readable=True)
     writable = DummyDispatcher(writable=True)
     error = DummyDispatcher(writable=True, error=OSError)
     pgroup.dispatchers = {6:readable, 7:writable, 8:error}
     supervisord.process_groups = {'foo': pgroup}
     options.test = True
     supervisord.runforever()
     self.assertEqual(pgroup.transitioned, True)
     self.assertEqual(readable.read_event_handled, True)
     self.assertEqual(writable.write_event_handled, True)
     self.assertEqual(error.error_handled, True)
예제 #23
0
    def test_remove_process_group(self):
        options = DummyOptions()
        pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
        gconfig = DummyPGroupConfig(options, 'foo', pconfigs=[pconfig])
        supervisord = self._makeOne(options)

        self.assertRaises(KeyError, supervisord.remove_process_group, 'asdf')

        supervisord.add_process_group(gconfig)
        result = supervisord.remove_process_group('foo')
        self.assertEqual(supervisord.process_groups, {})
        self.assertTrue(result)

        supervisord.add_process_group(gconfig)
        supervisord.process_groups['foo'].unstopped_processes = [DummyProcess(None)]
        result = supervisord.remove_process_group('foo')
        self.assertEqual(list(supervisord.process_groups.keys()), ['foo'])
        self.assertTrue(not result)
예제 #24
0
 def test_record_output_capturemode_string_longer_than_token(self):
     # stdout/stderr goes to the process log and the main log,
     # in capturemode, the length of the data needs to be longer
     # than the capture token to make it out.
     options = DummyOptions()
     from supervisor import loggers
     options.loglevel = loggers.LevelsByName.TRAC
     config = DummyPConfig(options, 'process1', '/bin/process1',
                           stdout_logfile='/tmp/foo',
                           stdout_capture_maxbytes=100)
     process = DummyProcess(config)
     dispatcher = self._makeOne(process)
     dispatcher.output_buffer = 'stdout string longer than a token'
     dispatcher.record_output()
     self.assertEqual(dispatcher.childlog.data,
                      ['stdout string longer than a token'])
     self.assertEqual(options.logger.data[0],
          "'process1' stdout output:\nstdout string longer than a token")
예제 #25
0
    def test_remove_process_group_event(self):
        from supervisor import events
        L = []
        def callback(event):
            L.append(1)
        events.subscribe(events.ProcessGroupRemovedEvent, callback)
        options = DummyOptions()
        pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
        gconfig = DummyPGroupConfig(options,'foo', pconfigs=[pconfig])
        options.process_group_configs = [gconfig]
        supervisord = self._makeOne(options)

        supervisord.add_process_group(gconfig)
        supervisord.process_groups['foo'].stopped_processes = [DummyProcess(None)]
        supervisord.remove_process_group('foo')
        options.test = True
        supervisord.runforever()

        self.assertEqual(L, [1])
예제 #26
0
    def test_record_output_emits_stdout_event_when_enabled(self):
        options = DummyOptions()
        config = DummyPConfig(options, 'process1', '/bin/process1',
                              stdout_events_enabled=True)
        process = DummyProcess(config)
        dispatcher = self._makeOne(process, 'stdout')
        dispatcher.output_buffer = 'hello from stdout'

        L = []
        def doit(event):
            L.append(event)
        from supervisor import events
        events.subscribe(events.EventTypes.PROCESS_LOG_STDOUT, doit)
        dispatcher.record_output()

        self.assertEqual(len(L), 1)
        event = L[0]
        self.assertEqual(event.process, process)
        self.assertEqual(event.data, 'hello from stdout') 
예제 #27
0
 def test_runforever_stopping_emits_events(self):
     options = DummyOptions()
     supervisord = self._makeOne(options)
     gconfig = DummyPGroupConfig(options)
     pgroup = DummyProcessGroup(gconfig)
     supervisord.process_groups = {'foo': pgroup}
     supervisord.options.mood = SupervisorStates.SHUTDOWN
     L = []
     def callback(event):
         L.append(event)
     from supervisor import events
     events.subscribe(events.SupervisorStateChangeEvent, callback)
     from supervisor.medusa import asyncore_25 as asyncore
     options.test = True
     self.assertRaises(asyncore.ExitNow, supervisord.runforever)
     self.assertTrue(pgroup.all_stopped)
     self.assertTrue(isinstance(L[0], events.SupervisorRunningEvent))
     self.assertTrue(isinstance(L[0], events.SupervisorStateChangeEvent))
     self.assertTrue(isinstance(L[1], events.SupervisorStoppingEvent))
     self.assertTrue(isinstance(L[1], events.SupervisorStateChangeEvent))
예제 #28
0
 def test_handle_listener_state_change_busy_to_acknowledged_rejected(self):
     options = DummyOptions()
     config = DummyPConfig(options, 'process1', '/bin/process1')
     process = DummyProcess(config)
     from supervisor.dispatchers import EventListenerStates
     dispatcher = self._makeOne(process)
     process.listener_state = EventListenerStates.BUSY
     class Dummy:
         pass
     process.group = Dummy()
     process.group.config = Dummy()
     from supervisor.dispatchers import default_handler
     process.group.config.result_handler = default_handler
     dispatcher.state_buffer = 'RESULT 4\nFAILabc'
     self.assertEqual(dispatcher.handle_listener_state_change(), None)
     self.assertEqual(dispatcher.state_buffer, 'abc')
     self.assertEqual(options.logger.data[0],
                      'process1: BUSY -> ACKNOWLEDGED (rejected)')
     self.assertEqual(process.listener_state,
                      EventListenerStates.ACKNOWLEDGED)
예제 #29
0
    def test_diff_add_remove(self):
        options = DummyOptions()
        supervisord = self._makeOne(options)

        pconfig = DummyPConfig(options, 'process1', 'process1')
        group1 = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])

        pconfig = DummyPConfig(options, 'process2', 'process2')
        group2 = DummyPGroupConfig(options, 'group2', pconfigs=[pconfig])

        new = [group1, group2]

        added, changed, removed = supervisord.diff_to_active()
        self.assertEqual(added, [])
        self.assertEqual(changed, [])
        self.assertEqual(removed, [])

        added, changed, removed = supervisord.diff_to_active(new)
        self.assertEqual(added, new)
        self.assertEqual(changed, [])
        self.assertEqual(removed, [])

        supervisord.options.process_group_configs = new
        added, changed, removed = supervisord.diff_to_active()
        self.assertEqual(added, new)

        supervisord.add_process_group(group1)
        supervisord.add_process_group(group2)

        pconfig = DummyPConfig(options, 'process3', 'process3')
        new_group1 = DummyPGroupConfig(options, pconfigs=[pconfig])

        pconfig = DummyPConfig(options, 'process4', 'process4')
        new_group2 = DummyPGroupConfig(options, pconfigs=[pconfig])

        new = [group2, new_group1, new_group2]

        added, changed, removed = supervisord.diff_to_active(new)
        self.assertEqual(added, [new_group1, new_group2])
        self.assertEqual(changed, [])
        self.assertEqual(removed, [group1])
예제 #30
0
 def test_process_state_exited_event_unexpected(self):
     from supervisor import events
     from supervisor.states import ProcessStates
     options = DummyOptions()
     pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
     process1 = DummyProcess(pconfig1)
     class DummyGroup:
         config = pconfig1
     process1.group = DummyGroup
     process1.pid = 1
     event = events.ProcessStateExitedEvent(process1,
                                            ProcessStates.STARTING,
                                            expected=False)
     headers, payload = self._deserialize(str(event))
     self.assertEqual(len(headers), 5)
     self.assertEqual(headers['processname'], 'process1')
     self.assertEqual(headers['groupname'], 'process1')
     self.assertEqual(headers['pid'], '1')
     self.assertEqual(headers['from_state'], 'STARTING')
     self.assertEqual(headers['expected'], '0')
     self.assertEqual(payload, '')