test_supervisord.py 23 KB

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