test_supervisord.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. import unittest
  2. import time
  3. import signal
  4. import sys
  5. import os
  6. import tempfile
  7. import shutil
  8. from supervisor.tests.base import DummyOptions
  9. from supervisor.tests.base import DummyPConfig
  10. from supervisor.tests.base import DummyPGroupConfig
  11. from supervisor.tests.base import DummyProcess
  12. from supervisor.tests.base import DummyProcessGroup
  13. from supervisor.tests.base import DummyDispatcher
  14. class EntryPointTests(unittest.TestCase):
  15. def test_main_noprofile(self):
  16. from supervisor.supervisord import main
  17. conf = os.path.join(
  18. os.path.abspath(os.path.dirname(__file__)), 'fixtures',
  19. 'donothing.conf')
  20. import StringIO
  21. new_stdout = StringIO.StringIO()
  22. old_stdout = sys.stdout
  23. try:
  24. tempdir = tempfile.mkdtemp()
  25. log = os.path.join(tempdir, 'log')
  26. pid = os.path.join(tempdir, 'pid')
  27. sys.stdout = new_stdout
  28. main(args=['-c', conf, '-l', log, '-j', pid, '-n'],
  29. test=True)
  30. finally:
  31. sys.stdout = old_stdout
  32. shutil.rmtree(tempdir)
  33. output = new_stdout.getvalue()
  34. self.assertTrue(output.find('supervisord started') != 1, output)
  35. if sys.version_info[:2] >= (2, 4):
  36. def test_main_profile(self):
  37. from supervisor.supervisord import main
  38. conf = os.path.join(
  39. os.path.abspath(os.path.dirname(__file__)), 'fixtures',
  40. 'donothing.conf')
  41. import StringIO
  42. new_stdout = StringIO.StringIO()
  43. old_stdout = sys.stdout
  44. try:
  45. tempdir = tempfile.mkdtemp()
  46. log = os.path.join(tempdir, 'log')
  47. pid = os.path.join(tempdir, 'pid')
  48. sys.stdout = new_stdout
  49. main(args=['-c', conf, '-l', log, '-j', pid, '-n',
  50. '--profile_options=cumulative,calls'], test=True)
  51. finally:
  52. sys.stdout = old_stdout
  53. shutil.rmtree(tempdir)
  54. output = new_stdout.getvalue()
  55. self.assertTrue(output.find('cumulative time, call count') != -1,
  56. output)
  57. class SupervisordTests(unittest.TestCase):
  58. def tearDown(self):
  59. from supervisor.events import clear
  60. clear()
  61. def _getTargetClass(self):
  62. from supervisor.supervisord import Supervisor
  63. return Supervisor
  64. def _makeOne(self, options):
  65. return self._getTargetClass()(options)
  66. def test_main_first(self):
  67. options = DummyOptions()
  68. pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
  69. gconfigs = [DummyPGroupConfig(options,'foo', pconfigs=[pconfig])]
  70. options.process_group_configs = gconfigs
  71. options.test = True
  72. options.first = True
  73. supervisord = self._makeOne(options)
  74. supervisord.main()
  75. self.assertEqual(options.environment_processed, True)
  76. self.assertEqual(options.fds_cleaned_up, False)
  77. self.assertEqual(options.rlimits_set, True)
  78. self.assertEqual(options.make_logger_messages,
  79. (['setuid_called'], [], ['rlimits_set']))
  80. self.assertEqual(options.autochildlogdir_cleared, True)
  81. self.assertEqual(len(supervisord.process_groups), 1)
  82. self.assertEqual(supervisord.process_groups['foo'].config.options,
  83. options)
  84. self.assertEqual(options.environment_processed, True)
  85. self.assertEqual(options.httpservers_opened, True)
  86. self.assertEqual(options.signals_set, True)
  87. self.assertEqual(options.daemonized, True)
  88. self.assertEqual(options.pidfile_written, True)
  89. self.assertEqual(options.cleaned_up, True)
  90. def test_main_notfirst(self):
  91. options = DummyOptions()
  92. pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
  93. gconfigs = [DummyPGroupConfig(options,'foo', pconfigs=[pconfig])]
  94. options.process_group_configs = gconfigs
  95. options.test = True
  96. options.first = False
  97. supervisord = self._makeOne(options)
  98. supervisord.main()
  99. self.assertEqual(options.environment_processed, True)
  100. self.assertEqual(options.fds_cleaned_up, True)
  101. self.assertFalse(hasattr(options, 'rlimits_set'))
  102. self.assertEqual(options.make_logger_messages,
  103. (['setuid_called'], [], []))
  104. self.assertEqual(options.autochildlogdir_cleared, True)
  105. self.assertEqual(len(supervisord.process_groups), 1)
  106. self.assertEqual(supervisord.process_groups['foo'].config.options,
  107. options)
  108. self.assertEqual(options.environment_processed, True)
  109. self.assertEqual(options.httpservers_opened, True)
  110. self.assertEqual(options.signals_set, True)
  111. self.assertEqual(options.daemonized, False)
  112. self.assertEqual(options.pidfile_written, True)
  113. self.assertEqual(options.cleaned_up, True)
  114. def test_reap(self):
  115. options = DummyOptions()
  116. options.waitpid_return = 1, 1
  117. pconfig = DummyPConfig(options, 'process', 'process', '/bin/process1')
  118. process = DummyProcess(pconfig)
  119. process.drained = False
  120. process.killing = 1
  121. process.laststop = None
  122. process.waitstatus = None, None
  123. options.pidhistory = {1:process}
  124. supervisord = self._makeOne(options)
  125. supervisord.reap(once=True)
  126. self.assertEqual(process.finished, (1,1))
  127. def test_handle_sigterm(self):
  128. options = DummyOptions()
  129. options._signal = signal.SIGTERM
  130. supervisord = self._makeOne(options)
  131. supervisord.handle_signal()
  132. self.assertEqual(supervisord.options.mood, -1)
  133. self.assertEqual(options.logger.data[0],
  134. 'received SIGTERM indicating exit request')
  135. def test_handle_sigint(self):
  136. options = DummyOptions()
  137. options._signal = signal.SIGINT
  138. supervisord = self._makeOne(options)
  139. supervisord.handle_signal()
  140. self.assertEqual(supervisord.options.mood, -1)
  141. self.assertEqual(options.logger.data[0],
  142. 'received SIGINT indicating exit request')
  143. def test_handle_sigquit(self):
  144. options = DummyOptions()
  145. options._signal = signal.SIGQUIT
  146. supervisord = self._makeOne(options)
  147. supervisord.handle_signal()
  148. self.assertEqual(supervisord.options.mood, -1)
  149. self.assertEqual(options.logger.data[0],
  150. 'received SIGQUIT indicating exit request')
  151. def test_handle_sighup(self):
  152. options = DummyOptions()
  153. options._signal = signal.SIGHUP
  154. supervisord = self._makeOne(options)
  155. supervisord.handle_signal()
  156. self.assertEqual(supervisord.options.mood, 0)
  157. self.assertEqual(options.logger.data[0],
  158. 'received SIGHUP indicating restart request')
  159. def test_handle_sigchld(self):
  160. options = DummyOptions()
  161. options._signal = signal.SIGCHLD
  162. supervisord = self._makeOne(options)
  163. supervisord.handle_signal()
  164. self.assertEqual(supervisord.options.mood, 1)
  165. self.assertEqual(options.logger.data[0],
  166. 'received SIGCHLD indicating a child quit')
  167. def test_handle_sigusr2(self):
  168. options = DummyOptions()
  169. options._signal = signal.SIGUSR2
  170. pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
  171. from supervisor.process import ProcessStates
  172. process1 = DummyProcess(pconfig1, state=ProcessStates.STOPPING)
  173. process1.delay = time.time() - 1
  174. supervisord = self._makeOne(options)
  175. pconfigs = [DummyPConfig(options, 'foo', 'foo', '/bin/foo')]
  176. options.process_group_configs = DummyPGroupConfig(
  177. options, 'foo',
  178. pconfigs=pconfigs)
  179. supervisord.handle_signal()
  180. self.assertEqual(supervisord.options.mood, 1)
  181. self.assertEqual(options.logs_reopened, True)
  182. self.assertEqual(options.logger.data[0],
  183. 'received SIGUSR2 indicating log reopen request')
  184. def test_handle_unknown_signal(self):
  185. options = DummyOptions()
  186. options._signal = signal.SIGUSR1
  187. supervisord = self._makeOne(options)
  188. supervisord.handle_signal()
  189. self.assertEqual(supervisord.options.mood, 1)
  190. self.assertEqual(options.logger.data[0],
  191. 'received SIGUSR1 indicating nothing')
  192. def test_diff_add_remove(self):
  193. options = DummyOptions()
  194. supervisord = self._makeOne(options)
  195. pconfig = DummyPConfig(options, 'process1', 'process1')
  196. group1 = DummyPGroupConfig(options, 'group1', pconfigs=[pconfig])
  197. pconfig = DummyPConfig(options, 'process2', 'process2')
  198. group2 = DummyPGroupConfig(options, 'group2', pconfigs=[pconfig])
  199. new = [group1, group2]
  200. added, changed, removed = supervisord.diff_to_active()
  201. self.assertEqual(added, [])
  202. self.assertEqual(changed, [])
  203. self.assertEqual(removed, [])
  204. added, changed, removed = supervisord.diff_to_active(new)
  205. self.assertEqual(added, new)
  206. self.assertEqual(changed, [])
  207. self.assertEqual(removed, [])
  208. supervisord.options.process_group_configs = new
  209. added, changed, removed = supervisord.diff_to_active()
  210. self.assertEqual(added, new)
  211. supervisord.add_process_group(group1)
  212. supervisord.add_process_group(group2)
  213. pconfig = DummyPConfig(options, 'process3', 'process3')
  214. new_group1 = DummyPGroupConfig(options, pconfigs=[pconfig])
  215. pconfig = DummyPConfig(options, 'process4', 'process4')
  216. new_group2 = DummyPGroupConfig(options, pconfigs=[pconfig])
  217. new = [group2, new_group1, new_group2]
  218. added, changed, removed = supervisord.diff_to_active(new)
  219. self.assertEqual(added, [new_group1, new_group2])
  220. self.assertEqual(changed, [])
  221. self.assertEqual(removed, [group1])
  222. def test_diff_changed(self):
  223. from supervisor.options import ProcessConfig, ProcessGroupConfig
  224. options = DummyOptions()
  225. supervisord = self._makeOne(options)
  226. def make_pconfig(name, command, **params):
  227. result = {
  228. 'name': name, 'command': command,
  229. 'directory': None, 'umask': None, 'priority': 999, 'autostart': True,
  230. 'autorestart': True, 'startsecs': 10, 'startretries': 999,
  231. 'uid': None, 'stdout_logfile': None, 'stdout_capture_maxbytes': 0,
  232. 'stdout_events_enabled': False,
  233. 'stdout_logfile_backups': 0, 'stdout_logfile_maxbytes': 0,
  234. 'stdout_syslog': False,
  235. 'stderr_logfile': None, 'stderr_capture_maxbytes': 0,
  236. 'stderr_events_enabled': False,
  237. 'stderr_logfile_backups': 0, 'stderr_logfile_maxbytes': 0,
  238. 'stderr_syslog': False,
  239. 'redirect_stderr': False,
  240. 'stopsignal': None, 'stopwaitsecs': 10,
  241. 'stopasgroup': False,
  242. 'killasgroup': False,
  243. 'exitcodes': (0,2), 'environment': None, 'serverurl': None,
  244. }
  245. result.update(params)
  246. return ProcessConfig(options, **result)
  247. def make_gconfig(name, pconfigs):
  248. return ProcessGroupConfig(options, name, 25, pconfigs)
  249. pconfig = make_pconfig('process1', 'process1', uid='new')
  250. group1 = make_gconfig('group1', [pconfig])
  251. pconfig = make_pconfig('process2', 'process2')
  252. group2 = make_gconfig('group2', [pconfig])
  253. new = [group1, group2]
  254. pconfig = make_pconfig('process1', 'process1', uid='old')
  255. group3 = make_gconfig('group1', [pconfig])
  256. pconfig = make_pconfig('process2', 'process2')
  257. group4 = make_gconfig('group2', [pconfig])
  258. supervisord.add_process_group(group3)
  259. supervisord.add_process_group(group4)
  260. added, changed, removed = supervisord.diff_to_active(new)
  261. self.assertEqual([added, removed], [[], []])
  262. self.assertEqual(changed, [group1])
  263. options = DummyOptions()
  264. supervisord = self._makeOne(options)
  265. pconfig1 = make_pconfig('process1', 'process1')
  266. pconfig2 = make_pconfig('process2', 'process2')
  267. group1 = make_gconfig('group1', [pconfig1, pconfig2])
  268. new = [group1]
  269. supervisord.add_process_group(make_gconfig('group1', [pconfig1]))
  270. added, changed, removed = supervisord.diff_to_active(new)
  271. self.assertEqual([added, removed], [[], []])
  272. self.assertEqual(changed, [group1])
  273. def test_add_process_group(self):
  274. options = DummyOptions()
  275. pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
  276. gconfig = DummyPGroupConfig(options,'foo', pconfigs=[pconfig])
  277. options.process_group_configs = [gconfig]
  278. supervisord = self._makeOne(options)
  279. self.assertEqual(supervisord.process_groups, {})
  280. result = supervisord.add_process_group(gconfig)
  281. self.assertEqual(supervisord.process_groups.keys(), ['foo'])
  282. self.assertTrue(result)
  283. group = supervisord.process_groups['foo']
  284. result = supervisord.add_process_group(gconfig)
  285. self.assertEqual(group, supervisord.process_groups['foo'])
  286. self.assertTrue(not result)
  287. def test_add_process_group_event(self):
  288. from supervisor import events
  289. L = []
  290. def callback(event):
  291. L.append(1)
  292. events.subscribe(events.ProcessGroupAddedEvent, callback)
  293. options = DummyOptions()
  294. pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
  295. gconfig = DummyPGroupConfig(options,'foo', pconfigs=[pconfig])
  296. options.process_group_configs = [gconfig]
  297. supervisord = self._makeOne(options)
  298. supervisord.add_process_group(gconfig)
  299. options.test = True
  300. supervisord.runforever()
  301. self.assertEqual(L, [1])
  302. def test_remove_process_group(self):
  303. options = DummyOptions()
  304. pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
  305. gconfig = DummyPGroupConfig(options, 'foo', pconfigs=[pconfig])
  306. supervisord = self._makeOne(options)
  307. self.assertRaises(KeyError, supervisord.remove_process_group, 'asdf')
  308. supervisord.add_process_group(gconfig)
  309. result = supervisord.remove_process_group('foo')
  310. self.assertEqual(supervisord.process_groups, {})
  311. self.assertTrue(result)
  312. supervisord.add_process_group(gconfig)
  313. supervisord.process_groups['foo'].unstopped_processes = [DummyProcess(None)]
  314. result = supervisord.remove_process_group('foo')
  315. self.assertEqual(supervisord.process_groups.keys(), ['foo'])
  316. self.assertTrue(not result)
  317. def test_remove_process_group_event(self):
  318. from supervisor import events
  319. L = []
  320. def callback(event):
  321. L.append(1)
  322. events.subscribe(events.ProcessGroupRemovedEvent, callback)
  323. options = DummyOptions()
  324. pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
  325. gconfig = DummyPGroupConfig(options,'foo', pconfigs=[pconfig])
  326. options.process_group_configs = [gconfig]
  327. supervisord = self._makeOne(options)
  328. supervisord.add_process_group(gconfig)
  329. supervisord.process_groups['foo'].stopped_processes = [DummyProcess(None)]
  330. supervisord.remove_process_group('foo')
  331. options.test = True
  332. supervisord.runforever()
  333. self.assertEqual(L, [1])
  334. def test_runforever_emits_generic_startup_event(self):
  335. from supervisor import events
  336. L = []
  337. def callback(event):
  338. L.append(1)
  339. events.subscribe(events.SupervisorStateChangeEvent, callback)
  340. options = DummyOptions()
  341. supervisord = self._makeOne(options)
  342. options.test = True
  343. supervisord.runforever()
  344. self.assertEqual(L, [1])
  345. def test_runforever_emits_generic_specific_event(self):
  346. from supervisor import events
  347. L = []
  348. def callback(event):
  349. L.append(2)
  350. events.subscribe(events.SupervisorRunningEvent, callback)
  351. options = DummyOptions()
  352. options.test = True
  353. supervisord = self._makeOne(options)
  354. supervisord.runforever()
  355. self.assertEqual(L, [2])
  356. def test_runforever_calls_tick(self):
  357. options = DummyOptions()
  358. options.test = True
  359. supervisord = self._makeOne(options)
  360. self.assertEqual(len(supervisord.ticks), 0)
  361. supervisord.runforever()
  362. self.assertEqual(len(supervisord.ticks), 3)
  363. def test_runforever_select_eintr(self):
  364. options = DummyOptions()
  365. import errno
  366. options.select_error = errno.EINTR
  367. supervisord = self._makeOne(options)
  368. options.test = True
  369. supervisord.runforever()
  370. self.assertEqual(options.logger.data[0], 'EINTR encountered in select')
  371. def test_runforever_select_uncaught_exception(self):
  372. options = DummyOptions()
  373. import errno
  374. options.select_error = errno.EBADF
  375. supervisord = self._makeOne(options)
  376. import select
  377. options.test = True
  378. self.assertRaises(select.error, supervisord.runforever)
  379. def test_runforever_select_dispatchers(self):
  380. options = DummyOptions()
  381. supervisord = self._makeOne(options)
  382. pconfig = DummyPConfig(options, 'foo', '/bin/foo',)
  383. gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
  384. pgroup = DummyProcessGroup(gconfig)
  385. readable = DummyDispatcher(readable=True)
  386. writable = DummyDispatcher(writable=True)
  387. error = DummyDispatcher(writable=True, error=OSError)
  388. pgroup.dispatchers = {6:readable, 7:writable, 8:error}
  389. supervisord.process_groups = {'foo': pgroup}
  390. options.select_result = [6], [7, 8], []
  391. options.test = True
  392. supervisord.runforever()
  393. self.assertEqual(pgroup.transitioned, True)
  394. self.assertEqual(readable.read_event_handled, True)
  395. self.assertEqual(writable.write_event_handled, True)
  396. self.assertEqual(error.error_handled, True)
  397. def test_runforever_select_dispatcher_exitnow(self):
  398. options = DummyOptions()
  399. supervisord = self._makeOne(options)
  400. pconfig = DummyPConfig(options, 'foo', '/bin/foo',)
  401. gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
  402. pgroup = DummyProcessGroup(gconfig)
  403. from supervisor.medusa import asyncore_25 as asyncore
  404. exitnow = DummyDispatcher(readable=True, error=asyncore.ExitNow)
  405. pgroup.dispatchers = {6:exitnow}
  406. supervisord.process_groups = {'foo': pgroup}
  407. options.select_result = [6], [], []
  408. options.test = True
  409. self.assertRaises(asyncore.ExitNow, supervisord.runforever)
  410. def test_runforever_stopping_emits_events(self):
  411. options = DummyOptions()
  412. supervisord = self._makeOne(options)
  413. gconfig = DummyPGroupConfig(options)
  414. pgroup = DummyProcessGroup(gconfig)
  415. supervisord.process_groups = {'foo': pgroup}
  416. supervisord.options.mood = -1
  417. L = []
  418. def callback(event):
  419. L.append(event)
  420. from supervisor import events
  421. events.subscribe(events.SupervisorStateChangeEvent, callback)
  422. from supervisor.medusa import asyncore_25 as asyncore
  423. options.test = True
  424. self.assertRaises(asyncore.ExitNow, supervisord.runforever)
  425. self.assertTrue(pgroup.all_stopped)
  426. self.assertTrue(isinstance(L[0], events.SupervisorRunningEvent))
  427. self.assertTrue(isinstance(L[0], events.SupervisorStateChangeEvent))
  428. self.assertTrue(isinstance(L[1], events.SupervisorStoppingEvent))
  429. self.assertTrue(isinstance(L[1], events.SupervisorStateChangeEvent))
  430. def test_exit(self):
  431. options = DummyOptions()
  432. supervisord = self._makeOne(options)
  433. pconfig = DummyPConfig(options, 'foo', '/bin/foo',)
  434. gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
  435. pgroup = DummyProcessGroup(gconfig)
  436. L = []
  437. def callback():
  438. L.append(1)
  439. supervisord.process_groups = {'foo': pgroup}
  440. supervisord.options.mood = 0
  441. supervisord.options.test = True
  442. from supervisor.medusa import asyncore_25 as asyncore
  443. self.assertRaises(asyncore.ExitNow, supervisord.runforever)
  444. self.assertEqual(pgroup.all_stopped, True)
  445. def test_exit_delayed(self):
  446. options = DummyOptions()
  447. supervisord = self._makeOne(options)
  448. pconfig = DummyPConfig(options, 'foo', '/bin/foo',)
  449. process = DummyProcess(pconfig)
  450. gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
  451. pgroup = DummyProcessGroup(gconfig)
  452. pgroup.unstopped_processes = [process]
  453. L = []
  454. def callback():
  455. L.append(1)
  456. supervisord.process_groups = {'foo': pgroup}
  457. supervisord.options.mood = 0
  458. supervisord.options.test = True
  459. supervisord.runforever()
  460. self.assertNotEqual(supervisord.lastshutdownreport, 0)
  461. def test_getSupervisorStateDescription(self):
  462. from supervisor.states import getSupervisorStateDescription
  463. from supervisor.states import SupervisorStates
  464. result = getSupervisorStateDescription(SupervisorStates.RUNNING)
  465. self.assertEqual(result, 'RUNNING')
  466. def test_tick(self):
  467. from supervisor import events
  468. L = []
  469. def callback(event):
  470. L.append(event)
  471. events.subscribe(events.TickEvent, callback)
  472. options = DummyOptions()
  473. supervisord = self._makeOne(options)
  474. supervisord.tick(now=0)
  475. self.assertEqual(supervisord.ticks[5], 0)
  476. self.assertEqual(supervisord.ticks[60], 0)
  477. self.assertEqual(supervisord.ticks[3600], 0)
  478. self.assertEqual(len(L), 0)
  479. supervisord.tick(now=6)
  480. self.assertEqual(supervisord.ticks[5], 5)
  481. self.assertEqual(supervisord.ticks[60], 0)
  482. self.assertEqual(supervisord.ticks[3600], 0)
  483. self.assertEqual(len(L), 1)
  484. self.assertEqual(L[-1].__class__, events.Tick5Event)
  485. supervisord.tick(now=61)
  486. self.assertEqual(supervisord.ticks[5], 60)
  487. self.assertEqual(supervisord.ticks[60], 60)
  488. self.assertEqual(supervisord.ticks[3600], 0)
  489. self.assertEqual(len(L), 3)
  490. self.assertEqual(L[-1].__class__, events.Tick60Event)
  491. supervisord.tick(now=3601)
  492. self.assertEqual(supervisord.ticks[5], 3600)
  493. self.assertEqual(supervisord.ticks[60], 3600)
  494. self.assertEqual(supervisord.ticks[3600], 3600)
  495. self.assertEqual(len(L), 6)
  496. self.assertEqual(L[-1].__class__, events.Tick3600Event)
  497. def test_suite():
  498. return unittest.findTestCases(sys.modules[__name__])
  499. if __name__ == '__main__':
  500. unittest.main(defaultTest='test_suite')