test_supervisorctl.py 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808
  1. import sys
  2. import unittest
  3. from supervisor.compat import StringIO
  4. from supervisor.compat import xmlrpclib
  5. from supervisor.tests.base import DummyRPCServer
  6. class ControllerTests(unittest.TestCase):
  7. def _getTargetClass(self):
  8. from supervisor.supervisorctl import Controller
  9. return Controller
  10. def _makeOne(self, options):
  11. return self._getTargetClass()(options)
  12. def test_ctor(self):
  13. options = DummyClientOptions()
  14. controller = self._makeOne(options)
  15. self.assertEqual(controller.prompt, options.prompt + '> ')
  16. def test__upcheck(self):
  17. options = DummyClientOptions()
  18. controller = self._makeOne(options)
  19. result = controller.upcheck()
  20. self.assertEqual(result, True)
  21. def test__upcheck_wrong_server_version(self):
  22. options = DummyClientOptions()
  23. options._server.supervisor.getVersion = lambda *x: '1.0'
  24. controller = self._makeOne(options)
  25. controller.stdout = StringIO()
  26. result = controller.upcheck()
  27. self.assertEqual(result, False)
  28. self.assertEqual(controller.stdout.getvalue(),
  29. 'Sorry, this version of supervisorctl expects'
  30. ' to talk to a server with API version 3.0, but'
  31. ' the remote version is 1.0.\n')
  32. def test__upcheck_unknown_method(self):
  33. options = DummyClientOptions()
  34. from supervisor.xmlrpc import Faults
  35. def getVersion():
  36. raise xmlrpclib.Fault(Faults.UNKNOWN_METHOD, 'duh')
  37. options._server.supervisor.getVersion = getVersion
  38. controller = self._makeOne(options)
  39. controller.stdout = StringIO()
  40. result = controller.upcheck()
  41. self.assertEqual(result, False)
  42. self.assertEqual(controller.stdout.getvalue(),
  43. 'Sorry, supervisord responded but did not recognize'
  44. ' the supervisor namespace commands that'
  45. ' supervisorctl uses to control it. Please check'
  46. ' that the [rpcinterface:supervisor] section is'
  47. ' enabled in the configuration file'
  48. ' (see sample.conf).\n')
  49. def test__upcheck_reraises_other_xmlrpc_faults(self):
  50. options = DummyClientOptions()
  51. from supervisor.xmlrpc import Faults
  52. def f(*arg, **kw):
  53. raise xmlrpclib.Fault(Faults.FAILED, '')
  54. options._server.supervisor.getVersion = f
  55. controller = self._makeOne(options)
  56. controller.stdout = StringIO()
  57. self.assertRaises(xmlrpclib.Fault, controller.upcheck)
  58. def test__upcheck_catches_socket_error_ECONNREFUSED(self):
  59. options = DummyClientOptions()
  60. import supervisor.medusa.text_socket as socket
  61. import errno
  62. def raise_fault(*arg, **kw):
  63. raise socket.error(errno.ECONNREFUSED, 'nobody home')
  64. options._server.supervisor.getVersion = raise_fault
  65. controller = self._makeOne(options)
  66. controller.stdout = StringIO()
  67. result = controller.upcheck()
  68. self.assertEqual(result, False)
  69. output = controller.stdout.getvalue()
  70. self.assertTrue('refused connection' in output)
  71. def test__upcheck_catches_socket_error_ENOENT(self):
  72. options = DummyClientOptions()
  73. import supervisor.medusa.text_socket as socket
  74. import errno
  75. def raise_fault(*arg, **kw):
  76. raise socket.error(errno.ENOENT, 'nobody home')
  77. options._server.supervisor.getVersion = raise_fault
  78. controller = self._makeOne(options)
  79. controller.stdout = StringIO()
  80. result = controller.upcheck()
  81. self.assertEqual(result, False)
  82. output = controller.stdout.getvalue()
  83. self.assertTrue('no such file' in output)
  84. def test__upcheck_reraises_other_socket_faults(self):
  85. options = DummyClientOptions()
  86. import supervisor.medusa.text_socket as socket
  87. import errno
  88. def f(*arg, **kw):
  89. raise socket.error(errno.EBADF, '')
  90. options._server.supervisor.getVersion = f
  91. controller = self._makeOne(options)
  92. controller.stdout = StringIO()
  93. self.assertRaises(socket.error, controller.upcheck)
  94. def test_onecmd(self):
  95. options = DummyClientOptions()
  96. controller = self._makeOne(options)
  97. controller.stdout = StringIO()
  98. plugin = DummyPlugin()
  99. controller.options.plugins = (plugin,)
  100. result = controller.onecmd('help')
  101. self.assertEqual(result, None)
  102. self.assertEqual(plugin.helped, True)
  103. def test_onecmd_multi_colonseparated(self):
  104. options = DummyClientOptions()
  105. controller = self._makeOne(options)
  106. controller.stdout = StringIO()
  107. plugin = DummyPlugin()
  108. controller.options.plugins = (plugin,)
  109. result = controller.onecmd('help; help')
  110. self.assertEqual(result, None)
  111. self.assertEqual(controller.cmdqueue, [' help'])
  112. self.assertEqual(plugin.helped, True)
  113. def test_onecmd_empty_does_not_repeat_previous_cmd(self):
  114. options = DummyClientOptions()
  115. controller = self._makeOne(options)
  116. controller.stdout = StringIO()
  117. plugin = DummyPlugin()
  118. controller.options.plugins = (plugin,)
  119. plugin.helped = False
  120. controller.onecmd('help')
  121. self.assertTrue(plugin.helped)
  122. plugin.helped = False
  123. controller.onecmd('')
  124. self.assertFalse(plugin.helped)
  125. def test_onecmd_clears_completion_cache(self):
  126. options = DummyClientOptions()
  127. controller = self._makeOne(options)
  128. controller.stdout = StringIO()
  129. controller._complete_info = {}
  130. controller.onecmd('help')
  131. self.assertEqual(controller._complete_info, None)
  132. def test_complete_action_empty(self):
  133. options = DummyClientOptions()
  134. controller = self._makeOne(options)
  135. controller.stdout=StringIO()
  136. controller.vocab = ['help']
  137. result = controller.complete('', 0, line='')
  138. self.assertEqual(result, 'help ')
  139. result = controller.complete('', 1, line='')
  140. self.assertEqual(result, None)
  141. def test_complete_action_partial(self):
  142. options = DummyClientOptions()
  143. controller = self._makeOne(options)
  144. controller.stdout=StringIO()
  145. controller.vocab = ['help']
  146. result = controller.complete('h', 0, line='h')
  147. self.assertEqual(result, 'help ')
  148. result = controller.complete('h', 1, line='h')
  149. self.assertEqual(result, None)
  150. def test_complete_action_whole(self):
  151. options = DummyClientOptions()
  152. controller = self._makeOne(options)
  153. controller.stdout=StringIO()
  154. controller.vocab = ['help']
  155. result = controller.complete('help', 0, line='help')
  156. self.assertEqual(result, 'help ')
  157. def test_complete_unknown_action_uncompletable(self):
  158. options = DummyClientOptions()
  159. controller = self._makeOne(options)
  160. controller.stdout=StringIO()
  161. result = controller.complete('bad', 0, line='bad')
  162. self.assertEqual(result, None)
  163. def test_complete_unknown_action_arg_uncompletable(self):
  164. options = DummyClientOptions()
  165. controller = self._makeOne(options)
  166. controller.stdout=StringIO()
  167. controller.vocab = ['help', 'add']
  168. result = controller.complete('', 1, line='bad ')
  169. self.assertEqual(result, None)
  170. def test_complete_help_empty(self):
  171. options = DummyClientOptions()
  172. controller = self._makeOne(options)
  173. controller.stdout=StringIO()
  174. controller.vocab = ['help', 'start']
  175. result = controller.complete('', 0, line='help ')
  176. self.assertEqual(result, 'help ')
  177. result = controller.complete('', 1, line='help ')
  178. self.assertEqual(result, 'start ')
  179. result = controller.complete('', 2, line='help ')
  180. self.assertEqual(result, None)
  181. def test_complete_help_action(self):
  182. options = DummyClientOptions()
  183. controller = self._makeOne(options)
  184. controller.stdout=StringIO()
  185. controller.vocab = ['help', 'start']
  186. result = controller.complete('he', 0, line='help he')
  187. self.assertEqual(result, 'help ')
  188. result = controller.complete('he', 1, line='help he')
  189. self.assertEqual(result, None)
  190. def test_complete_start_empty(self):
  191. options = DummyClientOptions()
  192. controller = self._makeOne(options)
  193. controller.stdout=StringIO()
  194. controller.vocab = ['help', 'start']
  195. result = controller.complete('', 0, line='start ')
  196. self.assertEqual(result, 'foo ')
  197. result = controller.complete('', 1, line='start ')
  198. self.assertEqual(result, 'bar ')
  199. result = controller.complete('', 2, line='start ')
  200. self.assertEqual(result, 'baz:baz_01 ')
  201. result = controller.complete('', 3, line='start ')
  202. self.assertEqual(result, 'baz:* ')
  203. result = controller.complete('', 4, line='start ')
  204. self.assertEqual(result, None)
  205. def test_complete_start_no_colon(self):
  206. options = DummyClientOptions()
  207. controller = self._makeOne(options)
  208. controller.stdout=StringIO()
  209. controller.vocab = ['help', 'start']
  210. result = controller.complete('f', 0, line='start f')
  211. self.assertEqual(result, 'foo ')
  212. result = controller.complete('f', 1, line='start f')
  213. self.assertEqual(result, None)
  214. def test_complete_start_with_colon(self):
  215. options = DummyClientOptions()
  216. controller = self._makeOne(options)
  217. controller.stdout=StringIO()
  218. controller.vocab = ['help', 'start']
  219. result = controller.complete('foo:', 0, line='start foo:')
  220. self.assertEqual(result, 'foo:foo ')
  221. result = controller.complete('foo:', 1, line='start foo:')
  222. self.assertEqual(result, 'foo:* ')
  223. result = controller.complete('foo:', 2, line='start foo:')
  224. self.assertEqual(result, None)
  225. def test_complete_start_uncompletable(self):
  226. options = DummyClientOptions()
  227. controller = self._makeOne(options)
  228. controller.stdout=StringIO()
  229. controller.vocab = ['help', 'start']
  230. result = controller.complete('bad', 0, line='start bad')
  231. self.assertEqual(result, None)
  232. def test_complete_caches_process_info(self):
  233. options = DummyClientOptions()
  234. controller = self._makeOne(options)
  235. controller.stdout=StringIO()
  236. controller.vocab = ['help', 'start']
  237. result = controller.complete('', 0, line='start ')
  238. self.assertNotEqual(result, None)
  239. def f(*arg, **kw):
  240. raise Exception("should not have called getAllProcessInfo")
  241. controller.options._server.supervisor.getAllProcessInfo = f
  242. controller.complete('', 1, line='start ')
  243. def test_complete_add_empty(self):
  244. options = DummyClientOptions()
  245. controller = self._makeOne(options)
  246. controller.stdout=StringIO()
  247. controller.vocab = ['help', 'add']
  248. result = controller.complete('', 0, line='add ')
  249. self.assertEqual(result, 'foo ')
  250. result = controller.complete('', 1, line='add ')
  251. self.assertEqual(result, 'bar ')
  252. result = controller.complete('', 2, line='add ')
  253. self.assertEqual(result, 'baz ')
  254. result = controller.complete('', 3, line='add ')
  255. self.assertEqual(result, None)
  256. def test_complete_add_uncompletable(self):
  257. options = DummyClientOptions()
  258. controller = self._makeOne(options)
  259. controller.stdout=StringIO()
  260. controller.vocab = ['help', 'add']
  261. result = controller.complete('bad', 0, line='add bad')
  262. self.assertEqual(result, None)
  263. def test_complete_add_group(self):
  264. options = DummyClientOptions()
  265. controller = self._makeOne(options)
  266. controller.stdout=StringIO()
  267. controller.vocab = ['help', 'add']
  268. result = controller.complete('f', 0, line='add f')
  269. self.assertEqual(result, 'foo ')
  270. result = controller.complete('f', 1, line='add f')
  271. self.assertEqual(result, None)
  272. def test_complete_reload_arg_uncompletable(self):
  273. options = DummyClientOptions()
  274. controller = self._makeOne(options)
  275. controller.stdout=StringIO()
  276. controller.vocab = ['help', 'reload']
  277. result = controller.complete('', 1, line='reload ')
  278. self.assertEqual(result, None)
  279. def test_complete_semicolon_separated_commands(self):
  280. options = DummyClientOptions()
  281. controller = self._makeOne(options)
  282. controller.stdout=StringIO()
  283. controller.vocab = ['help', 'start']
  284. result = controller.complete('f', 0, line='help;start f')
  285. self.assertEqual(result, 'foo ')
  286. result = controller.complete('f', 1, line='help;start f')
  287. self.assertEqual(result, None)
  288. def test_nohelp(self):
  289. options = DummyClientOptions()
  290. controller = self._makeOne(options)
  291. self.assertEqual(controller.nohelp, '*** No help on %s')
  292. def test_do_help(self):
  293. options = DummyClientOptions()
  294. controller = self._makeOne(options)
  295. controller.stdout = StringIO()
  296. results = controller.do_help('')
  297. helpval = controller.stdout.getvalue()
  298. self.assertEqual(results, None)
  299. self.assertEqual(helpval, 'foo helped')
  300. def test_do_help_for_help(self):
  301. options = DummyClientOptions()
  302. controller = self._makeOne(options)
  303. controller.stdout = StringIO()
  304. results = controller.do_help("help")
  305. self.assertEqual(results, None)
  306. helpval = controller.stdout.getvalue()
  307. self.assertTrue("help\t\tPrint a list" in helpval)
  308. def test_get_supervisor_returns_serverproxy_supervisor_namespace(self):
  309. options = DummyClientOptions()
  310. controller = self._makeOne(options)
  311. proxy = controller.get_supervisor()
  312. expected = options.getServerProxy().supervisor
  313. self.assertEqual(proxy, expected)
  314. def test_get_server_proxy_with_no_args_returns_serverproxy(self):
  315. options = DummyClientOptions()
  316. controller = self._makeOne(options)
  317. proxy = controller.get_server_proxy()
  318. expected = options.getServerProxy()
  319. self.assertEqual(proxy, expected)
  320. def test_get_server_proxy_with_namespace_returns_that_namespace(self):
  321. options = DummyClientOptions()
  322. controller = self._makeOne(options)
  323. proxy = controller.get_server_proxy('system')
  324. expected = options.getServerProxy().system
  325. self.assertEqual(proxy, expected)
  326. def test_real_controller_initialization(self):
  327. from supervisor.options import ClientOptions
  328. args = [] # simulating starting without parameters
  329. options = ClientOptions()
  330. # No default config file search in case they would exist
  331. self.assertTrue(len(options.searchpaths) > 0)
  332. options.searchpaths = []
  333. options.realize(args, doc=__doc__)
  334. self._makeOne(options) # should not raise
  335. class TestControllerPluginBase(unittest.TestCase):
  336. def _getTargetClass(self):
  337. from supervisor.supervisorctl import ControllerPluginBase
  338. return ControllerPluginBase
  339. def _makeOne(self, *arg, **kw):
  340. klass = self._getTargetClass()
  341. options = DummyClientOptions()
  342. ctl = DummyController(options)
  343. plugin = klass(ctl, *arg, **kw)
  344. return plugin
  345. def test_do_help_noarg(self):
  346. plugin = self._makeOne()
  347. result = plugin.do_help(None)
  348. self.assertEqual(result, None)
  349. self.assertEqual(plugin.ctl.stdout.getvalue(), '\n')
  350. self.assertEqual(len(plugin.ctl.topics_printed), 1)
  351. topics = plugin.ctl.topics_printed[0]
  352. self.assertEqual(topics[0], 'unnamed commands (type help <topic>):')
  353. self.assertEqual(topics[1], [])
  354. self.assertEqual(topics[2], 15)
  355. self.assertEqual(topics[3], 80)
  356. def test_do_help_witharg(self):
  357. plugin = self._makeOne()
  358. result = plugin.do_help('foo')
  359. self.assertEqual(result, None)
  360. self.assertEqual(plugin.ctl.stdout.getvalue(), 'no help on foo\n')
  361. self.assertEqual(len(plugin.ctl.topics_printed), 0)
  362. class TestDefaultControllerPlugin(unittest.TestCase):
  363. def _getTargetClass(self):
  364. from supervisor.supervisorctl import DefaultControllerPlugin
  365. return DefaultControllerPlugin
  366. def _makeOne(self, *arg, **kw):
  367. klass = self._getTargetClass()
  368. options = DummyClientOptions()
  369. ctl = DummyController(options)
  370. plugin = klass(ctl, *arg, **kw)
  371. return plugin
  372. def test_tail_toofewargs(self):
  373. plugin = self._makeOne()
  374. result = plugin.do_tail('')
  375. self.assertEqual(result, None)
  376. lines = plugin.ctl.stdout.getvalue().split('\n')
  377. self.assertEqual(lines[0], 'Error: too few arguments')
  378. def test_tail_toomanyargs(self):
  379. plugin = self._makeOne()
  380. result = plugin.do_tail('one two three four')
  381. self.assertEqual(result, None)
  382. lines = plugin.ctl.stdout.getvalue().split('\n')
  383. self.assertEqual(lines[0], 'Error: too many arguments')
  384. def test_tail_f_noprocname(self):
  385. plugin = self._makeOne()
  386. result = plugin.do_tail('-f')
  387. self.assertEqual(result, None)
  388. lines = plugin.ctl.stdout.getvalue().split('\n')
  389. self.assertEqual(lines[0], 'Error: tail requires process name')
  390. def test_tail_bad_modifier(self):
  391. plugin = self._makeOne()
  392. result = plugin.do_tail('-z foo')
  393. self.assertEqual(result, None)
  394. lines = plugin.ctl.stdout.getvalue().split('\n')
  395. self.assertEqual(lines[0], 'Error: bad argument -z')
  396. def test_tail_defaults(self):
  397. plugin = self._makeOne()
  398. result = plugin.do_tail('foo')
  399. self.assertEqual(result, None)
  400. lines = plugin.ctl.stdout.getvalue().split('\n')
  401. self.assertEqual(len(lines), 12)
  402. self.assertEqual(lines[0], 'output line')
  403. def test_tail_no_file(self):
  404. plugin = self._makeOne()
  405. result = plugin.do_tail('NO_FILE')
  406. self.assertEqual(result, None)
  407. lines = plugin.ctl.stdout.getvalue().split('\n')
  408. self.assertEqual(len(lines), 2)
  409. self.assertEqual(lines[0], 'NO_FILE: ERROR (no log file)')
  410. def test_tail_failed(self):
  411. plugin = self._makeOne()
  412. result = plugin.do_tail('FAILED')
  413. self.assertEqual(result, None)
  414. lines = plugin.ctl.stdout.getvalue().split('\n')
  415. self.assertEqual(len(lines), 2)
  416. self.assertEqual(lines[0], 'FAILED: ERROR (unknown error reading log)')
  417. def test_tail_bad_name(self):
  418. plugin = self._makeOne()
  419. result = plugin.do_tail('BAD_NAME')
  420. self.assertEqual(result, None)
  421. lines = plugin.ctl.stdout.getvalue().split('\n')
  422. self.assertEqual(len(lines), 2)
  423. self.assertEqual(lines[0], 'BAD_NAME: ERROR (no such process name)')
  424. def test_tail_bytesmodifier(self):
  425. plugin = self._makeOne()
  426. result = plugin.do_tail('-10 foo')
  427. self.assertEqual(result, None)
  428. lines = plugin.ctl.stdout.getvalue().split('\n')
  429. self.assertEqual(len(lines), 3)
  430. self.assertEqual(lines[0], 'tput line')
  431. def test_tail_explicit_channel_stdout_nomodifier(self):
  432. plugin = self._makeOne()
  433. result = plugin.do_tail('foo stdout')
  434. self.assertEqual(result, None)
  435. lines = plugin.ctl.stdout.getvalue().split('\n')
  436. self.assertEqual(len(lines), 12)
  437. self.assertEqual(lines[0], 'output line')
  438. def test_tail_explicit_channel_stderr_nomodifier(self):
  439. plugin = self._makeOne()
  440. result = plugin.do_tail('foo stderr')
  441. self.assertEqual(result, None)
  442. lines = plugin.ctl.stdout.getvalue().split('\n')
  443. self.assertEqual(len(lines), 12)
  444. self.assertEqual(lines[0], 'output line')
  445. def test_tail_explicit_channel_unrecognized(self):
  446. plugin = self._makeOne()
  447. result = plugin.do_tail('foo fudge')
  448. self.assertEqual(result, None)
  449. value = plugin.ctl.stdout.getvalue().strip()
  450. self.assertEqual(value, "Error: bad channel 'fudge'")
  451. def test_tail_upcheck_failed(self):
  452. plugin = self._makeOne()
  453. plugin.ctl.upcheck = lambda: False
  454. called = []
  455. def f(*arg, **kw):
  456. called.append(True)
  457. plugin.ctl.options._server.supervisor.readProcessStdoutLog = f
  458. plugin.do_tail('foo')
  459. self.assertEqual(called, [])
  460. def test_status_help(self):
  461. plugin = self._makeOne()
  462. plugin.help_status()
  463. out = plugin.ctl.stdout.getvalue()
  464. self.assertTrue("status <name>" in out)
  465. def test_status_upcheck_failed(self):
  466. plugin = self._makeOne()
  467. plugin.ctl.upcheck = lambda: False
  468. called = []
  469. def f(*arg, **kw):
  470. called.append(True)
  471. plugin.ctl.options._server.supervisor.getAllProcessInfo = f
  472. plugin.do_status('')
  473. self.assertEqual(called, [])
  474. def test_status_table_process_column_min_width(self):
  475. plugin = self._makeOne()
  476. result = plugin.do_status('')
  477. self.assertEqual(result, None)
  478. lines = plugin.ctl.stdout.getvalue().split("\n")
  479. self.assertEqual(lines[0].index("RUNNING"), 33)
  480. def test_status_table_process_column_expands(self):
  481. plugin = self._makeOne()
  482. options = plugin.ctl.options
  483. def f(*arg, **kw):
  484. from supervisor.states import ProcessStates
  485. return [{'name': 'foo'*50, # long name
  486. 'group':'foo',
  487. 'pid': 11,
  488. 'state': ProcessStates.RUNNING,
  489. 'statename': 'RUNNING',
  490. 'start': 0,
  491. 'stop': 0,
  492. 'spawnerr': '',
  493. 'now': 0,
  494. 'description':'foo description'},
  495. {
  496. 'name': 'bar', # short name
  497. 'group': 'bar',
  498. 'pid': 12,
  499. 'state': ProcessStates.FATAL,
  500. 'statename': 'RUNNING',
  501. 'start': 0,
  502. 'stop': 0,
  503. 'spawnerr': '',
  504. 'now': 0,
  505. 'description': 'bar description',
  506. }]
  507. options._server.supervisor.getAllProcessInfo = f
  508. self.assertEqual(plugin.do_status(''), None)
  509. lines = plugin.ctl.stdout.getvalue().split("\n")
  510. self.assertEqual(lines[0].index("RUNNING"), 157)
  511. self.assertEqual(lines[1].index("RUNNING"), 157)
  512. def test_status_all_processes_no_arg(self):
  513. plugin = self._makeOne()
  514. result = plugin.do_status('')
  515. self.assertEqual(result, None)
  516. value = plugin.ctl.stdout.getvalue().split('\n')
  517. self.assertEqual(value[0].split(None, 2),
  518. ['foo', 'RUNNING', 'foo description'])
  519. self.assertEqual(value[1].split(None, 2),
  520. ['bar', 'FATAL', 'bar description'])
  521. self.assertEqual(value[2].split(None, 2),
  522. ['baz:baz_01', 'STOPPED', 'baz description'])
  523. def test_status_all_processes_all_arg(self):
  524. plugin = self._makeOne()
  525. result = plugin.do_status('all')
  526. self.assertEqual(result, None)
  527. value = plugin.ctl.stdout.getvalue().split('\n')
  528. self.assertEqual(value[0].split(None, 2),
  529. ['foo', 'RUNNING', 'foo description'])
  530. self.assertEqual(value[1].split(None, 2),
  531. ['bar', 'FATAL', 'bar description'])
  532. self.assertEqual(value[2].split(None, 2),
  533. ['baz:baz_01', 'STOPPED', 'baz description'])
  534. def test_status_process_name(self):
  535. plugin = self._makeOne()
  536. result = plugin.do_status('foo')
  537. self.assertEqual(result, None)
  538. value = plugin.ctl.stdout.getvalue().strip()
  539. self.assertEqual(value.split(None, 2),
  540. ['foo', 'RUNNING', 'foo description'])
  541. def test_status_group_name(self):
  542. plugin = self._makeOne()
  543. result = plugin.do_status('baz:*')
  544. self.assertEqual(result, None)
  545. value = plugin.ctl.stdout.getvalue().split('\n')
  546. self.assertEqual(value[0].split(None, 2),
  547. ['baz:baz_01', 'STOPPED', 'baz description'])
  548. def test_status_mixed_names(self):
  549. plugin = self._makeOne()
  550. result = plugin.do_status('foo baz:*')
  551. self.assertEqual(result, None)
  552. value = plugin.ctl.stdout.getvalue().split('\n')
  553. self.assertEqual(value[0].split(None, 2),
  554. ['foo', 'RUNNING', 'foo description'])
  555. self.assertEqual(value[1].split(None, 2),
  556. ['baz:baz_01', 'STOPPED', 'baz description'])
  557. def test_status_bad_group_name(self):
  558. plugin = self._makeOne()
  559. result = plugin.do_status('badgroup:*')
  560. self.assertEqual(result, None)
  561. value = plugin.ctl.stdout.getvalue().split('\n')
  562. self.assertEqual(value[0], "badgroup: ERROR (no such group)")
  563. def test_status_bad_process_name(self):
  564. plugin = self._makeOne()
  565. result = plugin.do_status('badprocess')
  566. self.assertEqual(result, None)
  567. value = plugin.ctl.stdout.getvalue().split('\n')
  568. self.assertEqual(value[0], "badprocess: ERROR (no such process)")
  569. def test_status_bad_process_name_with_group(self):
  570. plugin = self._makeOne()
  571. result = plugin.do_status('badgroup:badprocess')
  572. self.assertEqual(result, None)
  573. value = plugin.ctl.stdout.getvalue().split('\n')
  574. self.assertEqual(value[0], "badgroup:badprocess: "
  575. "ERROR (no such process)")
  576. def test_start_help(self):
  577. plugin = self._makeOne()
  578. plugin.help_start()
  579. out = plugin.ctl.stdout.getvalue()
  580. self.assertTrue("start <name>" in out)
  581. def test_start_fail(self):
  582. plugin = self._makeOne()
  583. result = plugin.do_start('')
  584. self.assertEqual(result, None)
  585. expected = "Error: start requires a process name"
  586. self.assertEqual(plugin.ctl.stdout.getvalue().split('\n')[0], expected)
  587. def test_start_badname(self):
  588. plugin = self._makeOne()
  589. result = plugin.do_start('BAD_NAME')
  590. self.assertEqual(result, None)
  591. self.assertEqual(plugin.ctl.stdout.getvalue(),
  592. 'BAD_NAME: ERROR (no such process)\n')
  593. def test_start_no_file(self):
  594. plugin = self._makeOne()
  595. result = plugin.do_start('NO_FILE')
  596. self.assertEqual(result, None)
  597. self.assertEqual(plugin.ctl.stdout.getvalue(),
  598. 'NO_FILE: ERROR (no such file)\n')
  599. def test_start_not_executable(self):
  600. plugin = self._makeOne()
  601. result = plugin.do_start('NOT_EXECUTABLE')
  602. self.assertEqual(result, None)
  603. self.assertEqual(plugin.ctl.stdout.getvalue(),
  604. 'NOT_EXECUTABLE: ERROR (file is not executable)\n')
  605. def test_start_alreadystarted(self):
  606. plugin = self._makeOne()
  607. result = plugin.do_start('ALREADY_STARTED')
  608. self.assertEqual(result, None)
  609. self.assertEqual(plugin.ctl.stdout.getvalue(),
  610. 'ALREADY_STARTED: ERROR (already started)\n')
  611. def test_start_spawnerror(self):
  612. plugin = self._makeOne()
  613. result = plugin.do_start('SPAWN_ERROR')
  614. self.assertEqual(result, None)
  615. self.assertEqual(plugin.ctl.stdout.getvalue(),
  616. 'SPAWN_ERROR: ERROR (spawn error)\n')
  617. def test_start_abnormaltermination(self):
  618. plugin = self._makeOne()
  619. result = plugin.do_start('ABNORMAL_TERMINATION')
  620. self.assertEqual(result, None)
  621. expected = 'ABNORMAL_TERMINATION: ERROR (abnormal termination)\n'
  622. self.assertEqual(plugin.ctl.stdout.getvalue(), expected)
  623. def test_start_one_success(self):
  624. plugin = self._makeOne()
  625. result = plugin.do_start('foo')
  626. self.assertEqual(result, None)
  627. self.assertEqual(plugin.ctl.stdout.getvalue(),
  628. 'foo: started\n')
  629. def test_start_one_with_group_name_success(self):
  630. plugin = self._makeOne()
  631. result = plugin.do_start('foo:foo')
  632. self.assertEqual(result, None)
  633. self.assertEqual(plugin.ctl.stdout.getvalue(),
  634. 'foo: started\n')
  635. def test_start_many(self):
  636. plugin = self._makeOne()
  637. result = plugin.do_start('foo bar')
  638. self.assertEqual(result, None)
  639. self.assertEqual(plugin.ctl.stdout.getvalue(),
  640. 'foo: started\nbar: started\n')
  641. def test_start_group(self):
  642. plugin = self._makeOne()
  643. result = plugin.do_start('foo:')
  644. self.assertEqual(result, None)
  645. self.assertEqual(plugin.ctl.stdout.getvalue(),
  646. 'foo:foo_00: started\n'
  647. 'foo:foo_01: started\n')
  648. def test_start_group_bad_name(self):
  649. plugin = self._makeOne()
  650. result = plugin.do_start('BAD_NAME:')
  651. self.assertEqual(result, None)
  652. self.assertEqual(plugin.ctl.stdout.getvalue(),
  653. 'BAD_NAME: ERROR (no such group)\n')
  654. def test_start_all(self):
  655. plugin = self._makeOne()
  656. result = plugin.do_start('all')
  657. self.assertEqual(result, None)
  658. self.assertEqual(plugin.ctl.stdout.getvalue(),
  659. 'foo: started\n'
  660. 'foo2: started\n'
  661. 'failed_group:failed: ERROR (spawn error)\n')
  662. def test_start_upcheck_failed(self):
  663. plugin = self._makeOne()
  664. plugin.ctl.upcheck = lambda: False
  665. called = []
  666. def f(*arg, **kw):
  667. called.append(True)
  668. supervisor = plugin.ctl.options._server.supervisor
  669. supervisor.startAllProcesses = f
  670. supervisor.startProcessGroup = f
  671. plugin.do_start('foo')
  672. self.assertEqual(called, [])
  673. def test_stop_help(self):
  674. plugin = self._makeOne()
  675. plugin.help_stop()
  676. out = plugin.ctl.stdout.getvalue()
  677. self.assertTrue("stop <name>" in out)
  678. def test_stop_fail(self):
  679. plugin = self._makeOne()
  680. result = plugin.do_stop('')
  681. self.assertEqual(result, None)
  682. self.assertEqual(plugin.ctl.stdout.getvalue().split('\n')[0],
  683. "Error: stop requires a process name")
  684. def test_stop_badname(self):
  685. plugin = self._makeOne()
  686. result = plugin.do_stop('BAD_NAME')
  687. self.assertEqual(result, None)
  688. self.assertEqual(plugin.ctl.stdout.getvalue(),
  689. 'BAD_NAME: ERROR (no such process)\n')
  690. def test_stop_notrunning(self):
  691. plugin = self._makeOne()
  692. result = plugin.do_stop('NOT_RUNNING')
  693. self.assertEqual(result, None)
  694. self.assertEqual(plugin.ctl.stdout.getvalue(),
  695. 'NOT_RUNNING: ERROR (not running)\n')
  696. def test_stop_failed(self):
  697. plugin = self._makeOne()
  698. result = plugin.do_stop('FAILED')
  699. self.assertEqual(result, None)
  700. self.assertEqual(plugin.ctl.stdout.getvalue(), 'FAILED\n')
  701. def test_stop_one_success(self):
  702. plugin = self._makeOne()
  703. result = plugin.do_stop('foo')
  704. self.assertEqual(result, None)
  705. self.assertEqual(plugin.ctl.stdout.getvalue(),
  706. 'foo: stopped\n')
  707. def test_stop_one_with_group_name_success(self):
  708. plugin = self._makeOne()
  709. result = plugin.do_stop('foo:foo')
  710. self.assertEqual(result, None)
  711. self.assertEqual(plugin.ctl.stdout.getvalue(),
  712. 'foo: stopped\n')
  713. def test_stop_many(self):
  714. plugin = self._makeOne()
  715. result = plugin.do_stop('foo bar')
  716. self.assertEqual(result, None)
  717. self.assertEqual(plugin.ctl.stdout.getvalue(),
  718. 'foo: stopped\n'
  719. 'bar: stopped\n')
  720. def test_stop_group(self):
  721. plugin = self._makeOne()
  722. result = plugin.do_stop('foo:')
  723. self.assertEqual(result, None)
  724. self.assertEqual(plugin.ctl.stdout.getvalue(),
  725. 'foo:foo_00: stopped\n'
  726. 'foo:foo_01: stopped\n')
  727. def test_stop_group_bad_name(self):
  728. plugin = self._makeOne()
  729. result = plugin.do_stop('BAD_NAME:')
  730. self.assertEqual(result, None)
  731. self.assertEqual(plugin.ctl.stdout.getvalue(),
  732. 'BAD_NAME: ERROR (no such group)\n')
  733. def test_stop_all(self):
  734. plugin = self._makeOne()
  735. result = plugin.do_stop('all')
  736. self.assertEqual(result, None)
  737. self.assertEqual(plugin.ctl.stdout.getvalue(),
  738. 'foo: stopped\n'
  739. 'foo2: stopped\n'
  740. 'failed_group:failed: ERROR (no such process)\n')
  741. def test_stop_upcheck_failed(self):
  742. plugin = self._makeOne()
  743. plugin.ctl.upcheck = lambda: False
  744. called = []
  745. def f(*arg, **kw):
  746. called.append(True)
  747. supervisor = plugin.ctl.options._server.supervisor
  748. supervisor.stopAllProcesses = f
  749. supervisor.stopProcessGroup = f
  750. plugin.do_stop('foo')
  751. self.assertEqual(called, [])
  752. def test_signal_help(self):
  753. plugin = self._makeOne()
  754. plugin.help_signal()
  755. out = plugin.ctl.stdout.getvalue()
  756. self.assertTrue("signal <signal name> <name>" in out)
  757. def test_signal_fail_no_arg(self):
  758. plugin = self._makeOne()
  759. result = plugin.do_signal('')
  760. self.assertEqual(result, None)
  761. msg = 'Error: signal requires a signal name and a process name'
  762. self.assertEqual(plugin.ctl.stdout.getvalue().split('\n')[0], msg)
  763. def test_signal_fail_one_arg(self):
  764. plugin = self._makeOne()
  765. result = plugin.do_signal('hup')
  766. self.assertEqual(result, None)
  767. msg = 'Error: signal requires a signal name and a process name'
  768. self.assertEqual(plugin.ctl.stdout.getvalue().split('\n')[0], msg)
  769. def test_signal_bad_signal(self):
  770. plugin = self._makeOne()
  771. result = plugin.do_signal('BAD_SIGNAL foo')
  772. self.assertEqual(result, None)
  773. self.assertEqual(plugin.ctl.stdout.getvalue(),
  774. 'foo: ERROR (bad signal name)\n')
  775. def test_signal_bad_name(self):
  776. plugin = self._makeOne()
  777. result = plugin.do_signal('HUP BAD_NAME')
  778. self.assertEqual(result, None)
  779. self.assertEqual(plugin.ctl.stdout.getvalue(),
  780. 'BAD_NAME: ERROR (no such process)\n')
  781. def test_signal_not_running(self):
  782. plugin = self._makeOne()
  783. result = plugin.do_signal('HUP NOT_RUNNING')
  784. self.assertEqual(result, None)
  785. self.assertEqual(plugin.ctl.stdout.getvalue(),
  786. 'NOT_RUNNING: ERROR (not running)\n')
  787. def test_signal_failed(self):
  788. plugin = self._makeOne()
  789. result = plugin.do_signal('HUP FAILED')
  790. self.assertEqual(result, None)
  791. self.assertEqual(plugin.ctl.stdout.getvalue(), 'FAILED\n')
  792. def test_signal_one_success(self):
  793. plugin = self._makeOne()
  794. result = plugin.do_signal('HUP foo')
  795. self.assertEqual(result, None)
  796. self.assertEqual(plugin.ctl.stdout.getvalue(), 'foo: signalled\n')
  797. def test_signal_many(self):
  798. plugin = self._makeOne()
  799. result = plugin.do_signal('HUP foo bar')
  800. self.assertEqual(result, None)
  801. self.assertEqual(plugin.ctl.stdout.getvalue(),
  802. 'foo: signalled\n'
  803. 'bar: signalled\n')
  804. def test_signal_group(self):
  805. plugin = self._makeOne()
  806. result = plugin.do_signal('HUP foo:')
  807. self.assertEqual(result, None)
  808. self.assertEqual(plugin.ctl.stdout.getvalue(),
  809. 'foo:foo_00: signalled\n'
  810. 'foo:foo_01: signalled\n')
  811. def test_signal_all(self):
  812. plugin = self._makeOne()
  813. result = plugin.do_signal('HUP all')
  814. self.assertEqual(result, None)
  815. self.assertEqual(plugin.ctl.stdout.getvalue(),
  816. 'foo: signalled\n'
  817. 'foo2: signalled\n'
  818. 'failed_group:failed: ERROR (no such process)\n')
  819. def test_restart_help(self):
  820. plugin = self._makeOne()
  821. plugin.help_restart()
  822. out = plugin.ctl.stdout.getvalue()
  823. self.assertTrue("restart <name>" in out)
  824. def test_restart_fail(self):
  825. plugin = self._makeOne()
  826. result = plugin.do_restart('')
  827. self.assertEqual(result, None)
  828. self.assertEqual(plugin.ctl.stdout.getvalue().split('\n')[0],
  829. 'Error: restart requires a process name')
  830. def test_restart_one(self):
  831. plugin = self._makeOne()
  832. result = plugin.do_restart('foo')
  833. self.assertEqual(result, None)
  834. self.assertEqual(plugin.ctl.stdout.getvalue(),
  835. 'foo: stopped\nfoo: started\n')
  836. def test_restart_all(self):
  837. plugin = self._makeOne()
  838. result = plugin.do_restart('all')
  839. self.assertEqual(result, None)
  840. self.assertEqual(plugin.ctl.stdout.getvalue(),
  841. 'foo: stopped\nfoo2: stopped\n'
  842. 'failed_group:failed: ERROR (no such process)\n'
  843. 'foo: started\nfoo2: started\n'
  844. 'failed_group:failed: ERROR (spawn error)\n')
  845. def test_restart_upcheck_failed(self):
  846. plugin = self._makeOne()
  847. plugin.ctl.upcheck = lambda: False
  848. called = []
  849. def f(*arg, **kw):
  850. called.append(True)
  851. supervisor = plugin.ctl.options._server.supervisor
  852. supervisor.stopAllProcesses = f
  853. supervisor.stopProcessGroup = f
  854. plugin.do_restart('foo')
  855. self.assertEqual(called, [])
  856. def test_clear_help(self):
  857. plugin = self._makeOne()
  858. plugin.help_clear()
  859. out = plugin.ctl.stdout.getvalue()
  860. self.assertTrue("clear <name>" in out)
  861. def test_clear_fail(self):
  862. plugin = self._makeOne()
  863. result = plugin.do_clear('')
  864. self.assertEqual(result, None)
  865. self.assertEqual(plugin.ctl.stdout.getvalue().split('\n')[0],
  866. "Error: clear requires a process name")
  867. def test_clear_badname(self):
  868. plugin = self._makeOne()
  869. result = plugin.do_clear('BAD_NAME')
  870. self.assertEqual(result, None)
  871. self.assertEqual(plugin.ctl.stdout.getvalue(),
  872. 'BAD_NAME: ERROR (no such process)\n')
  873. def test_clear_one_success(self):
  874. plugin = self._makeOne()
  875. result = plugin.do_clear('foo')
  876. self.assertEqual(result, None)
  877. self.assertEqual(plugin.ctl.stdout.getvalue(),
  878. 'foo: cleared\n')
  879. def test_clear_one_with_group_success(self):
  880. plugin = self._makeOne()
  881. result = plugin.do_clear('foo:foo')
  882. self.assertEqual(result, None)
  883. self.assertEqual(plugin.ctl.stdout.getvalue(),
  884. 'foo: cleared\n')
  885. def test_clear_many(self):
  886. plugin = self._makeOne()
  887. result = plugin.do_clear('foo bar')
  888. self.assertEqual(result, None)
  889. self.assertEqual(plugin.ctl.stdout.getvalue(),
  890. 'foo: cleared\nbar: cleared\n')
  891. def test_clear_all(self):
  892. plugin = self._makeOne()
  893. result = plugin.do_clear('all')
  894. self.assertEqual(result, None)
  895. self.assertEqual(plugin.ctl.stdout.getvalue(),
  896. 'foo: cleared\n'
  897. 'foo2: cleared\n'
  898. 'failed_group:failed: ERROR (failed)\n')
  899. def test_clear_upcheck_failed(self):
  900. plugin = self._makeOne()
  901. plugin.ctl.upcheck = lambda: False
  902. called = []
  903. def f(*arg, **kw):
  904. called.append(True)
  905. supervisor = plugin.ctl.options._server.supervisor
  906. supervisor.clearAllProcessLogs = f
  907. supervisor.clearProcessLogs = f
  908. plugin.do_clear('foo')
  909. self.assertEqual(called, [])
  910. def test_open_help(self):
  911. plugin = self._makeOne()
  912. plugin.help_open()
  913. out = plugin.ctl.stdout.getvalue()
  914. self.assertTrue("open <url>" in out)
  915. def test_open_fail(self):
  916. plugin = self._makeOne()
  917. result = plugin.do_open('badname')
  918. self.assertEqual(result, None)
  919. self.assertEqual(plugin.ctl.stdout.getvalue(),
  920. 'ERROR: url must be http:// or unix://\n')
  921. def test_open_succeed(self):
  922. plugin = self._makeOne()
  923. result = plugin.do_open('http://localhost:9002')
  924. self.assertEqual(result, None)
  925. value = plugin.ctl.stdout.getvalue().split('\n')
  926. self.assertEqual(value[0].split(None, 2),
  927. ['foo', 'RUNNING', 'foo description'])
  928. self.assertEqual(value[1].split(None, 2),
  929. ['bar', 'FATAL', 'bar description'])
  930. self.assertEqual(value[2].split(None, 2),
  931. ['baz:baz_01', 'STOPPED', 'baz description'])
  932. def test_version_help(self):
  933. plugin = self._makeOne()
  934. plugin.help_version()
  935. out = plugin.ctl.stdout.getvalue()
  936. self.assertTrue("Show the version of the remote supervisord" in out)
  937. def test_version(self):
  938. plugin = self._makeOne()
  939. plugin.do_version(None)
  940. self.assertEqual(plugin.ctl.stdout.getvalue(), '3000\n')
  941. def test_version_upcheck_failed(self):
  942. plugin = self._makeOne()
  943. plugin.ctl.upcheck = lambda: False
  944. called = []
  945. def f(*arg, **kw):
  946. called.append(True)
  947. plugin.ctl.options._server.supervisor.getSupervisorVersion = f
  948. plugin.do_version('')
  949. self.assertEqual(called, [])
  950. def test_reload_help(self):
  951. plugin = self._makeOne()
  952. plugin.help_reload()
  953. out = plugin.ctl.stdout.getvalue()
  954. self.assertTrue("Restart the remote supervisord" in out)
  955. def test_reload_fail(self):
  956. plugin = self._makeOne()
  957. options = plugin.ctl.options
  958. options._server.supervisor._restartable = False
  959. result = plugin.do_reload('')
  960. self.assertEqual(result, None)
  961. self.assertEqual(options._server.supervisor._restarted, False)
  962. def test_reload(self):
  963. plugin = self._makeOne()
  964. options = plugin.ctl.options
  965. result = plugin.do_reload('')
  966. self.assertEqual(result, None)
  967. self.assertEqual(options._server.supervisor._restarted, True)
  968. def test_shutdown_help(self):
  969. plugin = self._makeOne()
  970. plugin.help_shutdown()
  971. out = plugin.ctl.stdout.getvalue()
  972. self.assertTrue("Shut the remote supervisord down" in out)
  973. def test_shutdown(self):
  974. plugin = self._makeOne()
  975. options = plugin.ctl.options
  976. result = plugin.do_shutdown('')
  977. self.assertEqual(result, None)
  978. self.assertEqual(options._server.supervisor._shutdown, True)
  979. def test_shutdown_catches_xmlrpc_fault_shutdown_state(self):
  980. plugin = self._makeOne()
  981. from supervisor import xmlrpc
  982. def raise_fault(*arg, **kw):
  983. raise xmlrpclib.Fault(xmlrpc.Faults.SHUTDOWN_STATE, 'bye')
  984. plugin.ctl.options._server.supervisor.shutdown = raise_fault
  985. result = plugin.do_shutdown('')
  986. self.assertEqual(result, None)
  987. self.assertEqual(plugin.ctl.stdout.getvalue(),
  988. 'ERROR: already shutting down\n')
  989. def test_shutdown_reraises_other_xmlrpc_faults(self):
  990. plugin = self._makeOne()
  991. from supervisor import xmlrpc
  992. def raise_fault(*arg, **kw):
  993. raise xmlrpclib.Fault(xmlrpc.Faults.CANT_REREAD, 'ouch')
  994. plugin.ctl.options._server.supervisor.shutdown = raise_fault
  995. self.assertRaises(xmlrpclib.Fault,
  996. plugin.do_shutdown, '')
  997. def test_shutdown_catches_socket_error_ECONNREFUSED(self):
  998. plugin = self._makeOne()
  999. import supervisor.medusa.text_socket as socket
  1000. import errno
  1001. def raise_fault(*arg, **kw):
  1002. raise socket.error(errno.ECONNREFUSED, 'nobody home')
  1003. plugin.ctl.options._server.supervisor.shutdown = raise_fault
  1004. result = plugin.do_shutdown('')
  1005. self.assertEqual(result, None)
  1006. output = plugin.ctl.stdout.getvalue()
  1007. self.assertTrue('refused connection (already shut down?)' in output)
  1008. def test_shutdown_catches_socket_error_ENOENT(self):
  1009. plugin = self._makeOne()
  1010. import supervisor.medusa.text_socket as socket
  1011. import errno
  1012. def raise_fault(*arg, **kw):
  1013. raise socket.error(errno.ENOENT, 'no file')
  1014. plugin.ctl.options._server.supervisor.shutdown = raise_fault
  1015. result = plugin.do_shutdown('')
  1016. self.assertEqual(result, None)
  1017. output = plugin.ctl.stdout.getvalue()
  1018. self.assertTrue('no such file (already shut down?)' in output)
  1019. def test_shutdown_reraises_other_socket_errors(self):
  1020. plugin = self._makeOne()
  1021. import supervisor.medusa.text_socket as socket
  1022. import errno
  1023. def raise_fault(*arg, **kw):
  1024. raise socket.error(errno.EPERM, 'denied')
  1025. plugin.ctl.options._server.supervisor.shutdown = raise_fault
  1026. self.assertRaises(socket.error,
  1027. plugin.do_shutdown, '')
  1028. def test__formatChanges(self):
  1029. plugin = self._makeOne()
  1030. # Don't explode, plz
  1031. plugin._formatChanges([['added'], ['changed'], ['removed']])
  1032. plugin._formatChanges([[], [], []])
  1033. def test_reread_help(self):
  1034. plugin = self._makeOne()
  1035. plugin.help_reread()
  1036. out = plugin.ctl.stdout.getvalue()
  1037. self.assertTrue("Reload the daemon's configuration files" in out)
  1038. def test_reread(self):
  1039. plugin = self._makeOne()
  1040. calls = []
  1041. plugin._formatChanges = lambda x: calls.append(x)
  1042. result = plugin.do_reread(None)
  1043. self.assertEqual(result, None)
  1044. self.assertEqual(calls[0], [['added'], ['changed'], ['removed']])
  1045. def test_reread_cant_reread(self):
  1046. plugin = self._makeOne()
  1047. from supervisor import xmlrpc
  1048. def reloadConfig(*arg, **kw):
  1049. raise xmlrpclib.Fault(xmlrpc.Faults.CANT_REREAD, 'cant')
  1050. plugin.ctl.options._server.supervisor.reloadConfig = reloadConfig
  1051. plugin.do_reread(None)
  1052. self.assertEqual(plugin.ctl.stdout.getvalue(),
  1053. 'ERROR: cant\n')
  1054. def test_reread_shutdown_state(self):
  1055. plugin = self._makeOne()
  1056. from supervisor import xmlrpc
  1057. def reloadConfig(*arg, **kw):
  1058. raise xmlrpclib.Fault(xmlrpc.Faults.SHUTDOWN_STATE, '')
  1059. plugin.ctl.options._server.supervisor.reloadConfig = reloadConfig
  1060. plugin.do_reread(None)
  1061. self.assertEqual(plugin.ctl.stdout.getvalue(),
  1062. 'ERROR: supervisor shutting down\n')
  1063. def test_reread_reraises_other_faults(self):
  1064. plugin = self._makeOne()
  1065. from supervisor import xmlrpc
  1066. def reloadConfig(*arg, **kw):
  1067. raise xmlrpclib.Fault(xmlrpc.Faults.FAILED, '')
  1068. plugin.ctl.options._server.supervisor.reloadConfig = reloadConfig
  1069. self.assertRaises(xmlrpclib.Fault, plugin.do_reread, '')
  1070. def test__formatConfigInfo(self):
  1071. info = { 'group': 'group1',
  1072. 'name': 'process1',
  1073. 'inuse': True,
  1074. 'autostart': True,
  1075. 'process_prio': 999,
  1076. 'group_prio': 999 }
  1077. plugin = self._makeOne()
  1078. result = plugin._formatConfigInfo(info)
  1079. self.assertTrue('in use' in result)
  1080. info = { 'group': 'group1',
  1081. 'name': 'process1',
  1082. 'inuse': False,
  1083. 'autostart': False,
  1084. 'process_prio': 999,
  1085. 'group_prio': 999 }
  1086. result = plugin._formatConfigInfo(info)
  1087. self.assertTrue('avail' in result)
  1088. def test_avail_help(self):
  1089. plugin = self._makeOne()
  1090. plugin.help_avail()
  1091. out = plugin.ctl.stdout.getvalue()
  1092. self.assertTrue("Display all configured" in out)
  1093. def test_avail(self):
  1094. calls = []
  1095. plugin = self._makeOne()
  1096. class FakeSupervisor(object):
  1097. def getAllConfigInfo(self):
  1098. return [{ 'group': 'group1', 'name': 'process1',
  1099. 'inuse': False, 'autostart': False,
  1100. 'process_prio': 999, 'group_prio': 999 }]
  1101. plugin.ctl.get_supervisor = lambda : FakeSupervisor()
  1102. plugin.ctl.output = calls.append
  1103. result = plugin.do_avail('')
  1104. self.assertEqual(result, None)
  1105. def test_avail_shutdown_state(self):
  1106. plugin = self._makeOne()
  1107. supervisor = plugin.ctl.options._server.supervisor
  1108. def getAllConfigInfo():
  1109. from supervisor import xmlrpc
  1110. raise xmlrpclib.Fault(xmlrpc.Faults.SHUTDOWN_STATE, '')
  1111. supervisor.getAllConfigInfo = getAllConfigInfo
  1112. result = plugin.do_avail('')
  1113. self.assertEqual(result, None)
  1114. self.assertEqual(plugin.ctl.stdout.getvalue(),
  1115. 'ERROR: supervisor shutting down\n')
  1116. def test_avail_reraises_other_faults(self):
  1117. plugin = self._makeOne()
  1118. supervisor = plugin.ctl.options._server.supervisor
  1119. def getAllConfigInfo():
  1120. from supervisor import xmlrpc
  1121. raise xmlrpclib.Fault(xmlrpc.Faults.FAILED, '')
  1122. supervisor.getAllConfigInfo = getAllConfigInfo
  1123. self.assertRaises(xmlrpclib.Fault, plugin.do_avail, '')
  1124. def test_add_help(self):
  1125. plugin = self._makeOne()
  1126. plugin.help_add()
  1127. out = plugin.ctl.stdout.getvalue()
  1128. self.assertTrue("add <name>" in out)
  1129. def test_add(self):
  1130. plugin = self._makeOne()
  1131. result = plugin.do_add('foo')
  1132. self.assertEqual(result, None)
  1133. supervisor = plugin.ctl.options._server.supervisor
  1134. self.assertEqual(supervisor.processes, ['foo'])
  1135. def test_add_already_added(self):
  1136. plugin = self._makeOne()
  1137. result = plugin.do_add('ALREADY_ADDED')
  1138. self.assertEqual(result, None)
  1139. self.assertEqual(plugin.ctl.stdout.getvalue(),
  1140. 'ERROR: process group already active\n')
  1141. def test_add_bad_name(self):
  1142. plugin = self._makeOne()
  1143. result = plugin.do_add('BAD_NAME')
  1144. self.assertEqual(result, None)
  1145. self.assertEqual(plugin.ctl.stdout.getvalue(),
  1146. 'ERROR: no such process/group: BAD_NAME\n')
  1147. def test_add_shutdown_state(self):
  1148. plugin = self._makeOne()
  1149. result = plugin.do_add('SHUTDOWN_STATE')
  1150. self.assertEqual(result, None)
  1151. self.assertEqual(plugin.ctl.stdout.getvalue(),
  1152. 'ERROR: shutting down\n')
  1153. def test_add_reraises_other_faults(self):
  1154. plugin = self._makeOne()
  1155. self.assertRaises(xmlrpclib.Fault, plugin.do_add, 'FAILED')
  1156. def test_remove_help(self):
  1157. plugin = self._makeOne()
  1158. plugin.help_remove()
  1159. out = plugin.ctl.stdout.getvalue()
  1160. self.assertTrue("remove <name>" in out)
  1161. def test_remove(self):
  1162. plugin = self._makeOne()
  1163. supervisor = plugin.ctl.options._server.supervisor
  1164. supervisor.processes = ['foo']
  1165. result = plugin.do_remove('foo')
  1166. self.assertEqual(result, None)
  1167. self.assertEqual(supervisor.processes, [])
  1168. def test_remove_bad_name(self):
  1169. plugin = self._makeOne()
  1170. supervisor = plugin.ctl.options._server.supervisor
  1171. supervisor.processes = ['foo']
  1172. result = plugin.do_remove('BAD_NAME')
  1173. self.assertEqual(result, None)
  1174. self.assertEqual(plugin.ctl.stdout.getvalue(),
  1175. 'ERROR: no such process/group: BAD_NAME\n')
  1176. def test_remove_still_running(self):
  1177. plugin = self._makeOne()
  1178. supervisor = plugin.ctl.options._server.supervisor
  1179. supervisor.processes = ['foo']
  1180. result = plugin.do_remove('STILL_RUNNING')
  1181. self.assertEqual(result, None)
  1182. self.assertEqual(plugin.ctl.stdout.getvalue(),
  1183. 'ERROR: process/group still running: STILL_RUNNING\n')
  1184. def test_remove_reraises_other_faults(self):
  1185. plugin = self._makeOne()
  1186. self.assertRaises(xmlrpclib.Fault, plugin.do_remove, 'FAILED')
  1187. def test_update_help(self):
  1188. plugin = self._makeOne()
  1189. plugin.help_update()
  1190. out = plugin.ctl.stdout.getvalue()
  1191. self.assertTrue("Reload config and add/remove" in out)
  1192. def test_update_not_on_shutdown(self):
  1193. plugin = self._makeOne()
  1194. supervisor = plugin.ctl.options._server.supervisor
  1195. def reloadConfig():
  1196. from supervisor import xmlrpc
  1197. raise xmlrpclib.Fault(xmlrpc.Faults.SHUTDOWN_STATE, 'blah')
  1198. supervisor.reloadConfig = reloadConfig
  1199. supervisor.processes = ['removed']
  1200. plugin.do_update('')
  1201. self.assertEqual(supervisor.processes, ['removed'])
  1202. def test_update_added_procs(self):
  1203. plugin = self._makeOne()
  1204. supervisor = plugin.ctl.options._server.supervisor
  1205. def reloadConfig():
  1206. return [[['new_proc'], [], []]]
  1207. supervisor.reloadConfig = reloadConfig
  1208. result = plugin.do_update('')
  1209. self.assertEqual(result, None)
  1210. self.assertEqual(supervisor.processes, ['new_proc'])
  1211. def test_update_with_gname(self):
  1212. plugin = self._makeOne()
  1213. supervisor = plugin.ctl.options._server.supervisor
  1214. def reloadConfig():
  1215. return [[['added1', 'added2'], ['changed'], ['removed']]]
  1216. supervisor.reloadConfig = reloadConfig
  1217. supervisor.processes = ['changed', 'removed']
  1218. plugin.do_update('changed')
  1219. self.assertEqual(sorted(supervisor.processes),
  1220. sorted(['changed', 'removed']))
  1221. plugin.do_update('added1 added2')
  1222. self.assertEqual(sorted(supervisor.processes),
  1223. sorted(['changed', 'removed', 'added1', 'added2']))
  1224. plugin.do_update('removed')
  1225. self.assertEqual(sorted(supervisor.processes),
  1226. sorted(['changed', 'added1', 'added2']))
  1227. supervisor.processes = ['changed', 'removed']
  1228. plugin.do_update('removed added1')
  1229. self.assertEqual(sorted(supervisor.processes),
  1230. sorted(['changed', 'added1']))
  1231. supervisor.processes = ['changed', 'removed']
  1232. plugin.do_update('all')
  1233. self.assertEqual(sorted(supervisor.processes),
  1234. sorted(['changed', 'added1', 'added2']))
  1235. def test_update_changed_procs(self):
  1236. from supervisor import xmlrpc
  1237. plugin = self._makeOne()
  1238. supervisor = plugin.ctl.options._server.supervisor
  1239. calls = []
  1240. def reloadConfig():
  1241. return [[[], ['changed_group'], []]]
  1242. supervisor.reloadConfig = reloadConfig
  1243. supervisor.startProcess = lambda x: calls.append(('start', x))
  1244. supervisor.addProcessGroup('changed_group') # fake existence
  1245. results = [{'name': 'changed_process',
  1246. 'group': 'changed_group',
  1247. 'status': xmlrpc.Faults.SUCCESS,
  1248. 'description': 'blah'}]
  1249. def stopProcessGroup(name):
  1250. calls.append(('stop', name))
  1251. return results
  1252. supervisor.stopProcessGroup = stopProcessGroup
  1253. plugin.do_update('')
  1254. self.assertEqual(calls, [('stop', 'changed_group')])
  1255. supervisor.addProcessGroup('changed_group') # fake existence
  1256. calls[:] = []
  1257. results[:] = [{'name': 'changed_process1',
  1258. 'group': 'changed_group',
  1259. 'status': xmlrpc.Faults.NOT_RUNNING,
  1260. 'description': 'blah'},
  1261. {'name': 'changed_process2',
  1262. 'group': 'changed_group',
  1263. 'status': xmlrpc.Faults.FAILED,
  1264. 'description': 'blah'}]
  1265. plugin.do_update('')
  1266. self.assertEqual(calls, [('stop', 'changed_group')])
  1267. supervisor.addProcessGroup('changed_group') # fake existence
  1268. calls[:] = []
  1269. results[:] = [{'name': 'changed_process1',
  1270. 'group': 'changed_group',
  1271. 'status': xmlrpc.Faults.FAILED,
  1272. 'description': 'blah'},
  1273. {'name': 'changed_process2',
  1274. 'group': 'changed_group',
  1275. 'status': xmlrpc.Faults.SUCCESS,
  1276. 'description': 'blah'}]
  1277. plugin.do_update('')
  1278. self.assertEqual(calls, [('stop', 'changed_group')])
  1279. def test_update_removed_procs(self):
  1280. from supervisor import xmlrpc
  1281. plugin = self._makeOne()
  1282. supervisor = plugin.ctl.options._server.supervisor
  1283. def reloadConfig():
  1284. return [[[], [], ['removed_group']]]
  1285. supervisor.reloadConfig = reloadConfig
  1286. results = [{'name': 'removed_process',
  1287. 'group': 'removed_group',
  1288. 'status': xmlrpc.Faults.SUCCESS,
  1289. 'description': 'blah'}]
  1290. supervisor.processes = ['removed_group']
  1291. def stopProcessGroup(name):
  1292. return results
  1293. supervisor.stopProcessGroup = stopProcessGroup
  1294. plugin.do_update('')
  1295. self.assertEqual(supervisor.processes, [])
  1296. results[:] = [{'name': 'removed_process',
  1297. 'group': 'removed_group',
  1298. 'status': xmlrpc.Faults.NOT_RUNNING,
  1299. 'description': 'blah'}]
  1300. supervisor.processes = ['removed_group']
  1301. plugin.do_update('')
  1302. self.assertEqual(supervisor.processes, [])
  1303. results[:] = [{'name': 'removed_process',
  1304. 'group': 'removed_group',
  1305. 'status': xmlrpc.Faults.FAILED,
  1306. 'description': 'blah'}]
  1307. supervisor.processes = ['removed_group']
  1308. plugin.do_update('')
  1309. self.assertEqual(supervisor.processes, ['removed_group'])
  1310. def test_update_reraises_other_faults(self):
  1311. plugin = self._makeOne()
  1312. supervisor = plugin.ctl.options._server.supervisor
  1313. def reloadConfig():
  1314. from supervisor import xmlrpc
  1315. raise xmlrpclib.Fault(xmlrpc.Faults.FAILED, 'FAILED')
  1316. supervisor.reloadConfig = reloadConfig
  1317. self.assertRaises(xmlrpclib.Fault, plugin.do_update, '')
  1318. def test_pid_help(self):
  1319. plugin = self._makeOne()
  1320. plugin.help_pid()
  1321. out = plugin.ctl.stdout.getvalue()
  1322. self.assertTrue("pid <name>" in out)
  1323. def test_pid_supervisord(self):
  1324. plugin = self._makeOne()
  1325. result = plugin.do_pid('')
  1326. self.assertEqual(result, None)
  1327. options = plugin.ctl.options
  1328. lines = plugin.ctl.stdout.getvalue().split('\n')
  1329. self.assertEqual(len(lines), 2)
  1330. self.assertEqual(lines[0], str(options._server.supervisor.getPID()))
  1331. def test_pid_allprocesses(self):
  1332. plugin = self._makeOne()
  1333. result = plugin.do_pid('all')
  1334. self.assertEqual(result, None)
  1335. value = plugin.ctl.stdout.getvalue().strip()
  1336. self.assertEqual(value.split(), ['11', '12', '13'])
  1337. def test_pid_badname(self):
  1338. plugin = self._makeOne()
  1339. result = plugin.do_pid('BAD_NAME')
  1340. self.assertEqual(result, None)
  1341. value = plugin.ctl.stdout.getvalue().strip()
  1342. self.assertEqual(value, 'No such process BAD_NAME')
  1343. def test_pid_oneprocess(self):
  1344. plugin = self._makeOne()
  1345. result = plugin.do_pid('foo')
  1346. self.assertEqual(result, None)
  1347. self.assertEqual(plugin.ctl.stdout.getvalue().strip(), '11')
  1348. def test_pid_upcheck_failed(self):
  1349. plugin = self._makeOne()
  1350. plugin.ctl.upcheck = lambda: False
  1351. called = []
  1352. def f(*arg, **kw):
  1353. called.append(True)
  1354. plugin.ctl.options._server.supervisor.getPID = f
  1355. plugin.do_pid('')
  1356. self.assertEqual(called, [])
  1357. def test_maintail_help(self):
  1358. plugin = self._makeOne()
  1359. plugin.help_maintail()
  1360. out = plugin.ctl.stdout.getvalue()
  1361. self.assertTrue("tail of supervisor main log file" in out)
  1362. def test_maintail_toomanyargs(self):
  1363. plugin = self._makeOne()
  1364. result = plugin.do_maintail('foo bar')
  1365. self.assertEqual(result, None)
  1366. val = plugin.ctl.stdout.getvalue()
  1367. self.assertTrue(val.startswith('Error: too many'), val)
  1368. def test_maintail_minus_string_fails(self):
  1369. plugin = self._makeOne()
  1370. result = plugin.do_maintail('-wrong')
  1371. self.assertEqual(result, None)
  1372. val = plugin.ctl.stdout.getvalue()
  1373. self.assertTrue(val.startswith('Error: bad argument -wrong'), val)
  1374. def test_maintail_wrong(self):
  1375. plugin = self._makeOne()
  1376. result = plugin.do_maintail('wrong')
  1377. self.assertEqual(result, None)
  1378. val = plugin.ctl.stdout.getvalue()
  1379. self.assertTrue(val.startswith('Error: bad argument wrong'), val)
  1380. def test_maintail_dashf(self):
  1381. plugin = self._makeOne()
  1382. plugin.listener = DummyListener()
  1383. result = plugin.do_maintail('-f')
  1384. self.assertEqual(result, None)
  1385. errors = plugin.listener.errors
  1386. self.assertEqual(len(errors), 1)
  1387. error = errors[0]
  1388. self.assertEqual(plugin.listener.closed,
  1389. 'http://localhost:65532/mainlogtail')
  1390. self.assertEqual(error[0],
  1391. 'http://localhost:65532/mainlogtail')
  1392. self.assertTrue('Cannot connect' in error[1])
  1393. def test_maintail_bad_modifier(self):
  1394. plugin = self._makeOne()
  1395. result = plugin.do_maintail('-z')
  1396. self.assertEqual(result, None)
  1397. lines = plugin.ctl.stdout.getvalue().split('\n')
  1398. self.assertEqual(lines[0], 'Error: bad argument -z')
  1399. def test_maintail_nobytes(self):
  1400. plugin = self._makeOne()
  1401. result = plugin.do_maintail('')
  1402. self.assertEqual(result, None)
  1403. self.assertEqual(plugin.ctl.stdout.getvalue(), 'mainlogdata\n')
  1404. def test_maintail_dashbytes(self):
  1405. plugin = self._makeOne()
  1406. result = plugin.do_maintail('-100')
  1407. self.assertEqual(result, None)
  1408. self.assertEqual(plugin.ctl.stdout.getvalue(), 'mainlogdata\n')
  1409. def test_maintail_readlog_error_nofile(self):
  1410. plugin = self._makeOne()
  1411. supervisor_rpc = plugin.ctl.get_supervisor()
  1412. from supervisor import xmlrpc
  1413. supervisor_rpc._readlog_error = xmlrpc.Faults.NO_FILE
  1414. result = plugin.do_maintail('-100')
  1415. self.assertEqual(result, None)
  1416. self.assertEqual(plugin.ctl.stdout.getvalue(),
  1417. 'supervisord: ERROR (no log file)\n')
  1418. def test_maintail_readlog_error_failed(self):
  1419. plugin = self._makeOne()
  1420. supervisor_rpc = plugin.ctl.get_supervisor()
  1421. from supervisor import xmlrpc
  1422. supervisor_rpc._readlog_error = xmlrpc.Faults.FAILED
  1423. result = plugin.do_maintail('-100')
  1424. self.assertEqual(result, None)
  1425. self.assertEqual(plugin.ctl.stdout.getvalue(),
  1426. 'supervisord: ERROR (unknown error reading log)\n')
  1427. def test_maintail_upcheck_failed(self):
  1428. plugin = self._makeOne()
  1429. plugin.ctl.upcheck = lambda: False
  1430. called = []
  1431. def f(*arg, **kw):
  1432. called.append(True)
  1433. plugin.ctl.options._server.supervisor.readLog = f
  1434. plugin.do_maintail('')
  1435. self.assertEqual(called, [])
  1436. def test_fg_help(self):
  1437. plugin = self._makeOne()
  1438. plugin.help_fg()
  1439. out = plugin.ctl.stdout.getvalue()
  1440. self.assertTrue("fg <process>" in out)
  1441. def test_fg_too_few_args(self):
  1442. plugin = self._makeOne()
  1443. result = plugin.do_fg('')
  1444. self.assertEqual(result, None)
  1445. lines = plugin.ctl.stdout.getvalue().split('\n')
  1446. self.assertEqual(lines[0], 'Error: no process name supplied')
  1447. def test_fg_too_many_args(self):
  1448. plugin = self._makeOne()
  1449. result = plugin.do_fg('foo bar')
  1450. self.assertEqual(result, None)
  1451. line = plugin.ctl.stdout.getvalue()
  1452. self.assertEqual(line, 'Error: too many process names supplied\n')
  1453. def test_fg_badprocname(self):
  1454. plugin = self._makeOne()
  1455. result = plugin.do_fg('BAD_NAME')
  1456. self.assertEqual(result, None)
  1457. line = plugin.ctl.stdout.getvalue()
  1458. self.assertEqual(line, 'Error: bad process name supplied\n')
  1459. def test_fg_procnotrunning(self):
  1460. plugin = self._makeOne()
  1461. result = plugin.do_fg('bar')
  1462. self.assertEqual(result, None)
  1463. line = plugin.ctl.stdout.getvalue()
  1464. self.assertEqual(line, 'Error: process not running\n')
  1465. result = plugin.do_fg('baz_01')
  1466. lines = plugin.ctl.stdout.getvalue().split('\n')
  1467. self.assertEqual(result, None)
  1468. self.assertEqual(lines[-2], 'Error: process not running')
  1469. def test_fg_upcheck_failed(self):
  1470. plugin = self._makeOne()
  1471. plugin.ctl.upcheck = lambda: False
  1472. called = []
  1473. def f(*arg, **kw):
  1474. called.append(True)
  1475. plugin.ctl.options._server.supervisor.getProcessInfo = f
  1476. plugin.do_fg('foo')
  1477. self.assertEqual(called, [])
  1478. def test_exit_help(self):
  1479. plugin = self._makeOne()
  1480. plugin.help_exit()
  1481. out = plugin.ctl.stdout.getvalue()
  1482. self.assertTrue("Exit the supervisor shell" in out)
  1483. def test_quit_help(self):
  1484. plugin = self._makeOne()
  1485. plugin.help_quit()
  1486. out = plugin.ctl.stdout.getvalue()
  1487. self.assertTrue("Exit the supervisor shell" in out)
  1488. class DummyListener:
  1489. def __init__(self):
  1490. self.errors = []
  1491. def error(self, url, msg):
  1492. self.errors.append((url, msg))
  1493. def close(self, url):
  1494. self.closed = url
  1495. class DummyPluginFactory:
  1496. def __init__(self, ctl, **kw):
  1497. self.ctl = ctl
  1498. def do_help(self, arg):
  1499. self.ctl.stdout.write('foo helped')
  1500. class DummyClientOptions:
  1501. def __init__(self):
  1502. self.prompt = 'supervisor'
  1503. self.serverurl = 'http://localhost:65532'
  1504. self.username = 'chrism'
  1505. self.password = '123'
  1506. self.history_file = None
  1507. self.plugins = ()
  1508. self._server = DummyRPCServer()
  1509. self.interactive = False
  1510. self.plugin_factories = [('dummy', DummyPluginFactory, {})]
  1511. def getServerProxy(self):
  1512. return self._server
  1513. class DummyController:
  1514. nohelp = 'no help on %s'
  1515. def __init__(self, options):
  1516. self.options = options
  1517. self.topics_printed = []
  1518. self.stdout = StringIO()
  1519. def upcheck(self):
  1520. return True
  1521. def get_supervisor(self):
  1522. return self.get_server_proxy('supervisor')
  1523. def get_server_proxy(self, namespace=None):
  1524. proxy = self.options.getServerProxy()
  1525. if namespace is None:
  1526. return proxy
  1527. else:
  1528. return getattr(proxy, namespace)
  1529. def output(self, data):
  1530. self.stdout.write(data + '\n')
  1531. def print_topics(self, doc_headers, cmds_doc, rows, cols):
  1532. self.topics_printed.append((doc_headers, cmds_doc, rows, cols))
  1533. class DummyPlugin:
  1534. def __init__(self, controller=None):
  1535. self.ctl = controller
  1536. def do_help(self, arg):
  1537. self.helped = True
  1538. def test_suite():
  1539. return unittest.findTestCases(sys.modules[__name__])
  1540. if __name__ == '__main__':
  1541. unittest.main(defaultTest='test_suite')