def test_runforever_calls_tick(self): options = DummyOptions() options.test = True supervisord = self._makeOne(options) self.assertEqual(len(supervisord.ticks), 0) supervisord.runforever() self.assertEqual(len(supervisord.ticks), 3)
def test_main_first(self): options = DummyOptions() pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo') gconfigs = [DummyPGroupConfig(options,'foo', pconfigs=[pconfig])] options.process_group_configs = gconfigs options.test = True options.first = True supervisord = self._makeOne(options) supervisord.main() self.assertEqual(options.environment_processed, True) self.assertEqual(options.fds_cleaned_up, False) self.assertEqual(options.rlimits_set, True) self.assertEqual(options.parse_criticals, ['setuid_called']) self.assertEqual(options.parse_warnings, []) self.assertEqual(options.parse_infos, ['rlimits_set']) self.assertEqual(options.autochildlogdir_cleared, True) self.assertEqual(len(supervisord.process_groups), 1) self.assertEqual(supervisord.process_groups['foo'].config.options, options) self.assertEqual(options.environment_processed, True) self.assertEqual(options.httpservers_opened, True) self.assertEqual(options.signals_set, True) self.assertEqual(options.daemonized, True) self.assertEqual(options.pidfile_written, True) self.assertEqual(options.cleaned_up, True)
def test_handle_sigint(self): options = DummyOptions() options._signal = signal.SIGINT supervisord = self._makeOne(options) supervisord.handle_signal() self.assertEqual(supervisord.options.mood, SupervisorStates.SHUTDOWN) self.assertEqual(options.logger.data[0], 'received SIGINT indicating exit request')
def test_handle_unknown_signal(self): options = DummyOptions() options._signal = signal.SIGUSR1 supervisord = self._makeOne(options) supervisord.handle_signal() self.assertEqual(supervisord.options.mood, 1) self.assertEqual(options.logger.data[0], 'received SIGUSR1 indicating nothing')
def test_handle_sigquit(self): options = DummyOptions() options._signal = signal.SIGQUIT supervisord = self._makeOne(options) supervisord.handle_signal() self.assertEqual(supervisord.options.mood, -1) self.assertEqual(options.logger.data[0], 'received SIGQUIT indicating exit request')
def test_handle_read_event(self): options = DummyOptions() options.readfd_result = "abc" config = DummyPConfig(options, "process1", "/bin/process1", stdout_capture_maxbytes=100) process = DummyProcess(config) dispatcher = self._makeOne(process) self.assertEqual(dispatcher.handle_read_event(), None) self.assertEqual(dispatcher.output_buffer, "abc")
def test_runforever_select_eintr(self): options = DummyOptions() import errno options.select_error = errno.EINTR supervisord = self._makeOne(options) options.test = True supervisord.runforever() self.assertEqual(options.logger.data[0], 'EINTR encountered in select')
def test_runforever_select_uncaught_exception(self): options = DummyOptions() import errno options.select_error = errno.EBADF supervisord = self._makeOne(options) import select options.test = True self.assertRaises(select.error, supervisord.runforever)
def test_handle_sighup(self): options = DummyOptions() options._signal = signal.SIGHUP supervisord = self._makeOne(options) supervisord.handle_signal() self.assertEqual(supervisord.options.mood, 0) self.assertEqual(options.logger.data[0], 'received SIGHUP indicating restart request')
def test_handle_sigabrt(self): options = DummyOptions() options._signal = signal.SIGABRT supervisord = self._makeOne(options) supervisord.handle_signal() self.assertEqual(supervisord.options.mood, SupervisorStates.RESTARTING) self.assertEqual(options.logger.data[0], 'received SIGABRT indicating restart request')
def test_handle_read_event_logging_childlog(self): options = DummyOptions() options.readfd_result = "supercalifragilisticexpialidocious" config = DummyPConfig(options, "process1", "/bin/process1", stdout_logfile="/tmp/foo") process = DummyProcess(config) dispatcher = self._makeOne(process) self.assertEqual(dispatcher.handle_read_event(), None) self.assertEqual(len(dispatcher.childlog.data), 1) self.assertEqual(dispatcher.childlog.data[0], "supercalifragilisticexpialidocious")
def test_handle_write_event_uncaught_raised(self): options = DummyOptions() config = DummyPConfig(options, 'test', '/test') process = DummyProcess(config) dispatcher = self._makeOne(process) dispatcher.input_buffer = 'halloooo' import errno options.write_error = errno.EBADF self.assertRaises(OSError, dispatcher.handle_write_event)
def test_handle_write_event_over_os_limit(self): options = DummyOptions() config = DummyPConfig(options, 'test', '/test') process = DummyProcess(config) dispatcher = self._makeOne(process) options.write_accept = 1 dispatcher.input_buffer = 'a' * 50 dispatcher.handle_write_event() self.assertEqual(len(dispatcher.input_buffer), 49) self.assertEqual(options.written[0], 'a')
def test_handle_read_event_logging_nologs(self): options = DummyOptions() options.readfd_result = 'supercalifragilisticexpialidocious' config = DummyPConfig(options, 'process1', '/bin/process1') process = DummyProcess(config) dispatcher = self._makeOne(process) # just make sure there are no errors if a child logger doesnt # exist self.assertEqual(dispatcher.handle_read_event(), None) self.assertEqual(dispatcher.childlog, None)
def test_handle_sigchld(self): options = DummyOptions() options._signal = signal.SIGCHLD supervisord = self._makeOne(options) supervisord.handle_signal() self.assertEqual(supervisord.options.mood, 1) # supervisor.options.signame(signal.SIGCHLD) may return "SIGCLD" # on linux or other systems where SIGCHLD = SIGCLD. msgs = ('received SIGCHLD indicating a child quit', 'received SIGCLD indicating a child quit') self.assertTrue(options.logger.data[0] in msgs)
def test_handle_read_event_nodata(self): options = DummyOptions() options.readfd_result = '' config = DummyPConfig(options, 'process1', '/bin/process1') process = DummyProcess(config) dispatcher = self._makeOne(process) self.assertEqual(dispatcher.handle_read_event(), None) self.assertEqual(dispatcher.state_buffer, '') from supervisor.dispatchers import EventListenerStates self.assertEqual(dispatcher.process.listener_state, EventListenerStates.ACKNOWLEDGED)
def test_runforever_emits_generic_specific_event(self): from supervisor import events L = [] def callback(event): L.append(2) events.subscribe(events.SupervisorRunningEvent, callback) options = DummyOptions() options.test = True supervisord = self._makeOne(options) supervisord.runforever() self.assertEqual(L, [2])
def test_handle_read_event_no_data_closes(self): options = DummyOptions() options.readfd_result = '' config = DummyPConfig(options, 'process1', '/bin/process1', stdout_capture_maxbytes=100) process = DummyProcess(config) dispatcher = self._makeOne(process) self.assertFalse(dispatcher.closed) self.assertEqual(dispatcher.handle_read_event(), None) self.assertEqual(dispatcher.output_buffer, '') self.assertTrue(dispatcher.closed)
def test_handle_read_event_logging_childlog(self): options = DummyOptions() options.readfd_result = 'supercalifragilisticexpialidocious' config = DummyPConfig(options, 'process1', '/bin/process1', stdout_logfile=os.path.join(tempfile.gettempdir(), 'foo.txt')) process = DummyProcess(config) dispatcher = self._makeOne(process) self.assertEqual(dispatcher.handle_read_event(), None) self.assertEqual(len(dispatcher.childlog.data), 1) self.assertEqual(dispatcher.childlog.data[0], 'supercalifragilisticexpialidocious')
def test_runforever_emits_generic_startup_event(self): from supervisor import events L = [] def callback(event): L.append(1) events.subscribe(events.SupervisorStateChangeEvent, callback) options = DummyOptions() supervisord = self._makeOne(options) options.test = True supervisord.runforever() self.assertEqual(L, [1])
def test_handle_sighup_in_shutdown_state(self): options = DummyOptions() options._signal = signal.SIGHUP supervisord = self._makeOne(options) supervisord.options.mood = SupervisorStates.SHUTDOWN self.assertEqual(supervisord.options.mood, SupervisorStates.SHUTDOWN) supervisord.handle_signal() self.assertEqual(supervisord.options.mood, SupervisorStates.SHUTDOWN) # unchanged self.assertEqual(options.logger.data[0], 'ignored SIGHUP indicating restart request ' '(shutdown in progress)')
def test_runforever_select_dispatcher_exitnow(self): options = DummyOptions() 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.select_result = [6], [], [] options.test = True self.assertRaises(asyncore.ExitNow, supervisord.runforever)
def test_handle_write_event_epipe_raised(self): options = DummyOptions() config = DummyPConfig(options, 'test', '/test') process = DummyProcess(config) dispatcher = self._makeOne(process) dispatcher.input_buffer = 'halloooo' import errno options.write_error = errno.EPIPE dispatcher.handle_write_event() self.assertEqual(dispatcher.input_buffer, '') self.assertTrue(options.logger.data[0].startswith( 'fd 0 closed, stopped monitoring')) self.assertTrue(options.logger.data[0].endswith('(stdin)>'))
def test_runforever_select_dispatcher_handle_error_via_write(self): options = DummyOptions() options.poller.result = [], [sys.stdout] 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 = {sys.stdout: notimpl} supervisord.process_groups = {'foo': pgroup} options.test = True supervisord.runforever() self.assertEqual(notimpl.error_handled, True)
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)
def test_reap(self): options = DummyOptions() options.waitpid_return = 1, 1 pconfig = DummyPConfig(options, 'process', 'process', '/bin/process1') process = DummyProcess(pconfig) process.drained = False process.killing = 1 process.laststop = None process.waitstatus = None, None options.pidhistory = {1:process} supervisord = self._makeOne(options) supervisord.reap(once=True) self.assertEqual(process.finished, (1,1))
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, "")
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(open(logfile, "r").read(), "") 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
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')
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=os.path.join(tempfile.gettempdir(), 'foo.txt')) 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, '')
def test_handle_listener_state_change_busy_to_acknowledged_procd(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 2\nOKabc' self.assertEqual(dispatcher.handle_listener_state_change(), None) self.assertEqual(dispatcher.state_buffer, 'abc') self.assertEqual(options.logger.data[0], 'process1: BUSY -> ACKNOWLEDGED (processed)') self.assertEqual(process.listener_state, EventListenerStates.ACKNOWLEDGED)
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 = 0 supervisord.options.test = True supervisord.runforever() self.assertNotEqual(supervisord.lastshutdownreport, 0)
def test_exit(self): options = DummyOptions() supervisord = self._makeOne(options) pconfig = DummyPConfig( options, 'foo', '/bin/foo', ) process = DummyProcess(pconfig) gconfig = DummyPGroupConfig(options, pconfigs=[pconfig]) pgroup = DummyProcessGroup(gconfig) L = [] def callback(): L.append(1) supervisord.process_groups = {'foo': pgroup} supervisord.options.mood = 0 supervisord.options.test = True from supervisor.medusa import asyncore_25 as asyncore self.assertRaises(asyncore.ExitNow, supervisord.runforever) self.assertEqual(pgroup.all_stopped, True)
def test_record_output_emits_stderr_event_when_enabled(self): options = DummyOptions() config = DummyPConfig(options, 'process1', '/bin/process1', stderr_events_enabled=True) 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), 1) event = L[0] self.assertEqual(event.process, process) self.assertEqual(event.data, 'hello from stderr')
def test_process_state_events_without_extra_values(self): from supervisor.states import ProcessStates from supervisor import events for klass in ( events.ProcessStateFatalEvent, events.ProcessStateUnknownEvent, ): options = DummyOptions() pconfig1 = DummyPConfig(options, 'process1', 'process1', '/bin/process1') class DummyGroup: config = pconfig1 process1 = DummyProcess(pconfig1) process1.group = DummyGroup event = klass(process1, ProcessStates.STARTING) headers, payload = self._deserialize(str(event)) self.assertEqual(len(headers), 3) self.assertEqual(headers['processname'], 'process1') self.assertEqual(headers['groupname'], 'process1') self.assertEqual(headers['from_state'], 'STARTING') self.assertEqual(payload, '')
def test_toggle_capturemode_sends_event(self): options = DummyOptions() config = DummyPConfig(options, 'process1', '/bin/process1', stdout_logfile=os.path.join(tempfile.gettempdir(), 'foo.txt'), stdout_capture_maxbytes=500) process = DummyProcess(config) process.pid = 4000 dispatcher = self._makeOne(process) dispatcher.capturemode = True dispatcher.capturelog.getvalue = lambda: 'hallooo' L = [] def doit(event): L.append(event) from supervisor import events events.subscribe(events.EventTypes.PROCESS_COMMUNICATION, doit) dispatcher.toggle_capturemode() self.assertEqual(len(L), 1) event = L[0] self.assertEqual(event.process, process) self.assertEqual(event.pid, 4000) self.assertEqual(event.data, 'hallooo')
def test_tick(self): from supervisor import events L = [] def callback(event): L.append(event) events.subscribe(events.TickEvent, callback) options = DummyOptions() supervisord = self._makeOne(options) supervisord.tick(now=0) self.assertEqual(supervisord.ticks[5], 0) self.assertEqual(supervisord.ticks[60], 0) self.assertEqual(supervisord.ticks[3600], 0) self.assertEqual(len(L), 0) supervisord.tick(now=6) self.assertEqual(supervisord.ticks[5], 5) self.assertEqual(supervisord.ticks[60], 0) self.assertEqual(supervisord.ticks[3600], 0) self.assertEqual(len(L), 1) self.assertEqual(L[-1].__class__, events.Tick5Event) supervisord.tick(now=61) self.assertEqual(supervisord.ticks[5], 60) self.assertEqual(supervisord.ticks[60], 60) self.assertEqual(supervisord.ticks[3600], 0) self.assertEqual(len(L), 3) self.assertEqual(L[-1].__class__, events.Tick60Event) supervisord.tick(now=3601) self.assertEqual(supervisord.ticks[5], 3600) self.assertEqual(supervisord.ticks[60], 3600) self.assertEqual(supervisord.ticks[3600], 3600) self.assertEqual(len(L), 6) self.assertEqual(L[-1].__class__, events.Tick3600Event)
def test_handle_listener_state_change_busy_to_unknown(self): from supervisor.events import EventRejectedEvent from supervisor.events import subscribe events = [] def doit(event): events.append(event) subscribe(EventRejectedEvent, doit) 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 current_event = DummyEvent() process.event = current_event dispatcher.state_buffer = 'bogus data\n' self.assertEqual(dispatcher.handle_listener_state_change(), None) self.assertEqual(dispatcher.state_buffer, '') self.assertEqual(options.logger.data[0], 'process1: BUSY -> UNKNOWN (bad result line \'bogus data\')') self.assertEqual(process.listener_state, EventListenerStates.UNKNOWN) self.assertEqual(events[0].process, process) self.assertEqual(events[0].event, current_event)
def test_process_state_events_with_pid(self): from supervisor.states import ProcessStates from supervisor import events for klass in ( events.ProcessStateRunningEvent, events.ProcessStateStoppedEvent, events.ProcessStateStoppingEvent, ): options = DummyOptions() pconfig1 = DummyPConfig(options, 'process1', 'process1', '/bin/process1') class DummyGroup: config = pconfig1 process1 = DummyProcess(pconfig1) process1.group = DummyGroup process1.pid = 1 event = klass(process1, ProcessStates.STARTING) headers, payload = self._deserialize(str(event)) self.assertEqual(len(headers), 4) self.assertEqual(headers['processname'], 'process1') self.assertEqual(headers['groupname'], 'process1') self.assertEqual(headers['from_state'], 'STARTING') self.assertEqual(headers['pid'], '1') self.assertEqual(payload, '')
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, '')
def test_strip_ansi(self): options = DummyOptions() options.strip_ansi = True config = DummyPConfig(options, 'process1', '/bin/process1', stdout_logfile='/tmp/foo') process = DummyProcess(config) dispatcher = self._makeOne(process) ansi = '\x1b[34mHello world... this is longer than a token!\x1b[0m' noansi = 'Hello world... this is longer than a token!' options.readfd_result = ansi dispatcher.handle_read_event() self.assertEqual(len(dispatcher.childlog.data), 1) self.assertEqual(dispatcher.childlog.data[0], noansi) options.strip_ansi = False options.readfd_result = ansi dispatcher.handle_read_event() self.assertEqual(len(dispatcher.childlog.data), 2) self.assertEqual(dispatcher.childlog.data[1], ansi)
def setUp(self): super(DependentStartupTestsBase, self).setUp() self.options = DummyOptions()
def test_register_uncaught_exception(self): _kqueue = DummyKQueue(raise_errno_register=errno.ENOMEM) options = DummyOptions() poller = self._makeOne(options) poller._kqueue = _kqueue self.assertRaises(OSError, poller.register_readable, 5)
def test_register_writable(self): select_poll = DummySelectPoll() poller = self._makeOne(DummyOptions()) poller._poller = select_poll poller.register_writable(6) self.assertEqual(select_poll.registered_as_writable, [6])
def test_register_writable(self): poller = self._makeOne(DummyOptions()) poller.register_writable(6) poller.register_writable(7) self.assertEqual(sorted(poller.writables), [6, 7])
def test_reap_recursionguard(self): options = DummyOptions() supervisord = self._makeOne(options) result = supervisord.reap(once=True, recursionguard=100) self.assertEqual(result, None)
def test_get_state(self): options = DummyOptions() supervisord = self._makeOne(options) self.assertEqual(supervisord.get_state(), SupervisorStates.RUNNING)
def test_diff_changed(self): from supervisor.options import ProcessConfig, ProcessGroupConfig options = DummyOptions() supervisord = self._makeOne(options) def make_pconfig(name, command, **params): result = { 'name': name, 'command': command, 'directory': None, 'umask': None, 'priority': 999, 'autostart': True, 'autorestart': True, 'startsecs': 10, 'startretries': 999, 'uid': None, 'stdout_logfile': None, 'stdout_capture_maxbytes': 0, 'stdout_events_enabled': False, 'stdout_logfile_backups': 0, 'stdout_logfile_maxbytes': 0, 'stdout_syslog': False, 'stderr_logfile': None, 'stderr_capture_maxbytes': 0, 'stderr_events_enabled': False, 'stderr_logfile_backups': 0, 'stderr_logfile_maxbytes': 0, 'stderr_syslog': False, 'redirect_stderr': False, 'stopsignal': None, 'stopwaitsecs': 10, 'stopasgroup': False, 'killasgroup': False, 'exitcodes': (0, ), 'environment': None, 'serverurl': None, } result.update(params) return ProcessConfig(options, **result) def make_gconfig(name, pconfigs): return ProcessGroupConfig(options, name, 25, pconfigs) pconfig = make_pconfig('process1', 'process1', uid='new') group1 = make_gconfig('group1', [pconfig]) pconfig = make_pconfig('process2', 'process2') group2 = make_gconfig('group2', [pconfig]) new = [group1, group2] pconfig = make_pconfig('process1', 'process1', uid='old') group3 = make_gconfig('group1', [pconfig]) pconfig = make_pconfig('process2', 'process2') group4 = make_gconfig('group2', [pconfig]) supervisord.add_process_group(group3) supervisord.add_process_group(group4) added, changed, removed = supervisord.diff_to_active(new) self.assertEqual([added, removed], [[], []]) self.assertEqual(changed, [group1]) options = DummyOptions() supervisord = self._makeOne(options) pconfig1 = make_pconfig('process1', 'process1') pconfig2 = make_pconfig('process2', 'process2') group1 = make_gconfig('group1', [pconfig1, pconfig2]) new = [group1] supervisord.add_process_group(make_gconfig('group1', [pconfig1])) added, changed, removed = supervisord.diff_to_active(new) self.assertEqual([added, removed], [[], []]) self.assertEqual(changed, [group1])
def test_writable(self): options = DummyOptions() config = DummyPConfig(options, 'process1', '/bin/process1') process = DummyProcess(config) dispatcher = self._makeOne(process) self.assertEqual(dispatcher.writable(), False)
def test_stdout_capturemode_multiple_buffers(self): from supervisor.events import ProcessCommunicationEvent from supervisor.events import subscribe events = [] def doit(event): events.append(event) subscribe(ProcessCommunicationEvent, doit) import string letters = string.letters digits = string.digits * 4 BEGIN_TOKEN = ProcessCommunicationEvent.BEGIN_TOKEN END_TOKEN = ProcessCommunicationEvent.END_TOKEN data = (letters + BEGIN_TOKEN + digits + END_TOKEN + letters) # boundaries that split tokens broken = data.split(':') first = broken[0] + ':' second = broken[1] + ':' third = broken[2] 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=10000) process = DummyProcess(config) dispatcher = self._makeOne(process) try: dispatcher.output_buffer = first dispatcher.record_output() [x.flush() for x in dispatcher.childlog.handlers] self.assertEqual(open(logfile, 'r').read(), letters) self.assertEqual(dispatcher.output_buffer, first[len(letters):]) self.assertEqual(len(events), 0) dispatcher.output_buffer += second dispatcher.record_output() self.assertEqual(len(events), 0) [x.flush() for x in dispatcher.childlog.handlers] self.assertEqual(open(logfile, 'r').read(), letters) self.assertEqual(dispatcher.output_buffer, first[len(letters):]) self.assertEqual(len(events), 0) dispatcher.output_buffer += third dispatcher.record_output() [x.flush() for x in dispatcher.childlog.handlers] self.assertEqual(open(logfile, 'r').read(), letters * 2) 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, digits) finally: try: os.remove(logfile) except (OSError, IOError): pass
def test_handle_write_event(self): options = DummyOptions() config = DummyPConfig(options, 'process1', '/bin/process1') process = DummyProcess(config) dispatcher = self._makeOne(process) self.assertRaises(NotImplementedError, dispatcher.handle_write_event)
def test_diff_changed_eventlistener(self): from supervisor.events import EventTypes from supervisor.options import EventListenerConfig, EventListenerPoolConfig options = DummyOptions() supervisord = self._makeOne(options) def make_pconfig(name, command, **params): result = { 'name': name, 'command': command, 'directory': None, 'umask': None, 'priority': 999, 'autostart': True, 'autorestart': True, 'startsecs': 10, 'startretries': 999, 'uid': None, 'stdout_logfile': None, 'stdout_capture_maxbytes': 0, 'stdout_events_enabled': False, 'stdout_logfile_backups': 0, 'stdout_logfile_maxbytes': 0, 'stdout_syslog': False, 'stderr_logfile': None, 'stderr_capture_maxbytes': 0, 'stderr_events_enabled': False, 'stderr_logfile_backups': 0, 'stderr_logfile_maxbytes': 0, 'stderr_syslog': False, 'redirect_stderr': False, 'stopsignal': None, 'stopwaitsecs': 10, 'stopasgroup': False, 'killasgroup': False, 'exitcodes': (0, ), 'environment': None, 'serverurl': None, } result.update(params) return EventListenerConfig(options, **result) def make_econfig(*pool_event_names): result = [] for pool_event_name in pool_event_names: result.append(getattr(EventTypes, pool_event_name, None)) return result def make_gconfig( name, pconfigs, pool_events, result_handler='supervisor.dispatchers:default_handler'): return EventListenerPoolConfig(options, name, 25, pconfigs, 10, pool_events, result_handler) # Test that changing an event listener command causes the diff_to_activate pconfig = make_pconfig('process1', 'process1-new') econfig = make_econfig("TICK_60") group1 = make_gconfig('group1', [pconfig], econfig) pconfig = make_pconfig('process2', 'process2') econfig = make_econfig("TICK_3600") group2 = make_gconfig('group2', [pconfig], econfig) new = [group1, group2] pconfig = make_pconfig('process1', 'process1-old') econfig = make_econfig("TICK_60") group3 = make_gconfig('group1', [pconfig], econfig) pconfig = make_pconfig('process2', 'process2') econfig = make_econfig("TICK_3600") group4 = make_gconfig('group2', [pconfig], econfig) supervisord.add_process_group(group3) supervisord.add_process_group(group4) added, changed, removed = supervisord.diff_to_active(new) self.assertEqual([added, removed], [[], []]) self.assertEqual(changed, [group1]) # Test that changing the event triggers diff_to_activate options = DummyOptions() supervisord = self._makeOne(options) pconfig = make_pconfig('process1', 'process1') econfig = make_econfig("TICK_60") group1 = make_gconfig('group1', [pconfig], econfig) pconfig = make_pconfig('process2', 'process2') econfig = make_econfig("TICK_3600") group2 = make_gconfig('group2', [pconfig], econfig) new = [group1, group2] pconfig = make_pconfig('process1', 'process1') econfig = make_econfig("TICK_5") group3 = make_gconfig('group1', [pconfig], econfig) pconfig = make_pconfig('process2', 'process2') econfig = make_econfig("TICK_3600") group4 = make_gconfig('group2', [pconfig], econfig) supervisord.add_process_group(group3) supervisord.add_process_group(group4) added, changed, removed = supervisord.diff_to_active(new) self.assertEqual([added, removed], [[], []]) self.assertEqual(changed, [group1]) # Test that changing the result_handler triggers diff_to_activate options = DummyOptions() supervisord = self._makeOne(options) pconfig = make_pconfig('process1', 'process1') econfig = make_econfig("TICK_60") group1 = make_gconfig('group1', [pconfig], econfig, 'new-result-handler') pconfig = make_pconfig('process2', 'process2') econfig = make_econfig("TICK_3600") group2 = make_gconfig('group2', [pconfig], econfig) new = [group1, group2] pconfig = make_pconfig('process1', 'process1') econfig = make_econfig("TICK_60") group3 = make_gconfig('group1', [pconfig], econfig, 'old-result-handler') pconfig = make_pconfig('process2', 'process2') econfig = make_econfig("TICK_3600") group4 = make_gconfig('group2', [pconfig], econfig) supervisord.add_process_group(group3) supervisord.add_process_group(group4) added, changed, removed = supervisord.diff_to_active(new) self.assertEqual([added, removed], [[], []]) self.assertEqual(changed, [group1])