TestMain.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #!/usr/bin/env python
  2. '''
  3. Licensed to the Apache Software Foundation (ASF) under one
  4. or more contributor license agreements. See the NOTICE file
  5. distributed with this work for additional information
  6. regarding copyright ownership. The ASF licenses this file
  7. to you under the Apache License, Version 2.0 (the
  8. "License"); you may not use this file except in compliance
  9. with the License. You may obtain a copy of the License at
  10. http://www.apache.org/licenses/LICENSE-2.0
  11. Unless required by applicable law or agreed to in writing, software
  12. distributed under the License is distributed on an "AS IS" BASIS,
  13. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. See the License for the specific language governing permissions and
  15. limitations under the License.
  16. '''
  17. import StringIO
  18. import sys
  19. from mock.mock import MagicMock, patch, ANY
  20. import unittest
  21. import logging
  22. import signal
  23. import ConfigParser
  24. import os
  25. import tempfile
  26. from optparse import OptionParser
  27. with patch("platform.linux_distribution", return_value = ('Suse','11','Final')):
  28. from ambari_agent import NetUtil, security
  29. from ambari_agent import ProcessHelper, main
  30. from ambari_agent import ProcessHelper, main
  31. from ambari_agent.AmbariConfig import AmbariConfig
  32. from ambari_agent.PingPortListener import PingPortListener
  33. from ambari_agent.Controller import Controller
  34. from ambari_agent.DataCleaner import DataCleaner
  35. class TestMain(unittest.TestCase):
  36. def setUp(self):
  37. # disable stdout
  38. out = StringIO.StringIO()
  39. sys.stdout = out
  40. def tearDown(self):
  41. # enable stdout
  42. sys.stdout = sys.__stdout__
  43. @patch("os._exit")
  44. @patch("os.getpid")
  45. @patch.object(ProcessHelper, "stopAgent")
  46. def test_signal_handler(self, stopAgent_mock, os_getpid_mock, os_exit_mock):
  47. # testing exit of children
  48. main.agentPid = 4444
  49. os_getpid_mock.return_value = 5555
  50. main.signal_handler("signum", "frame")
  51. self.assertTrue(os_exit_mock.called)
  52. os_exit_mock.reset_mock()
  53. # testing exit of main process
  54. os_getpid_mock.return_value = main.agentPid
  55. main.signal_handler("signum", "frame")
  56. self.assertFalse(os_exit_mock.called)
  57. self.assertTrue(stopAgent_mock.called)
  58. @patch.object(main.logger, "addHandler")
  59. @patch.object(main.logger, "setLevel")
  60. @patch("logging.handlers.RotatingFileHandler")
  61. def test_setup_logging(self, rfh_mock, setLevel_mock, addHandler_mock):
  62. # Testing silent mode
  63. main.setup_logging(False)
  64. self.assertTrue(addHandler_mock.called)
  65. setLevel_mock.assert_called_with(logging.INFO)
  66. addHandler_mock.reset_mock()
  67. setLevel_mock.reset_mock()
  68. # Testing verbose mode
  69. main.setup_logging(True)
  70. self.assertTrue(addHandler_mock.called)
  71. setLevel_mock.assert_called_with(logging.DEBUG)
  72. @patch.object(main.logger, "setLevel")
  73. @patch("logging.basicConfig")
  74. def test_update_log_level(self, basicConfig_mock, setLevel_mock):
  75. config = AmbariConfig().getConfig()
  76. # Testing with default setup (config file does not contain loglevel entry)
  77. # Log level should not be changed
  78. config.set('agent', 'loglevel', None)
  79. main.update_log_level(config)
  80. self.assertFalse(setLevel_mock.called)
  81. setLevel_mock.reset_mock()
  82. # Testing debug mode
  83. config.set('agent', 'loglevel', 'DEBUG')
  84. main.update_log_level(config)
  85. setLevel_mock.assert_called_with(logging.DEBUG)
  86. setLevel_mock.reset_mock()
  87. # Testing any other mode
  88. config.set('agent', 'loglevel', 'INFO')
  89. main.update_log_level(config)
  90. setLevel_mock.assert_called_with(logging.INFO)
  91. setLevel_mock.reset_mock()
  92. config.set('agent', 'loglevel', 'WRONG')
  93. main.update_log_level(config)
  94. setLevel_mock.assert_called_with(logging.INFO)
  95. @patch("signal.signal")
  96. def test_bind_signal_handlers(self, signal_mock):
  97. main.bind_signal_handlers()
  98. # Check if on SIGINT/SIGTERM agent is configured to terminate
  99. signal_mock.assert_any_call(signal.SIGINT, main.signal_handler)
  100. signal_mock.assert_any_call(signal.SIGTERM, main.signal_handler)
  101. # Check if on SIGUSR1 agent is configured to fall into debug
  102. signal_mock.assert_any_call(signal.SIGUSR1, main.debug)
  103. @patch("os.path.exists")
  104. @patch("ConfigParser.RawConfigParser.read")
  105. def test_resolve_ambari_config(self, read_mock, exists_mock):
  106. # Trying case if conf file exists
  107. exists_mock.return_value = True
  108. main.resolve_ambari_config()
  109. self.assertTrue(read_mock.called)
  110. exists_mock.reset_mock()
  111. read_mock.reset_mock()
  112. # Trying case if conf file does not exist
  113. exists_mock.return_value = False
  114. main.resolve_ambari_config()
  115. self.assertFalse(read_mock.called)
  116. @patch("sys.exit")
  117. @patch("os.path.isfile")
  118. @patch("os.path.isdir")
  119. @patch("hostname.hostname")
  120. def test_perform_prestart_checks(self, hostname_mock, isdir_mock, isfile_mock, exit_mock):
  121. main.config = AmbariConfig().getConfig()
  122. # Check expected hostname test
  123. hostname_mock.return_value = "test.hst"
  124. main.perform_prestart_checks("another.hst")
  125. self.assertTrue(exit_mock.called)
  126. exit_mock.reset_mock()
  127. # Trying case if there is another instance running
  128. isfile_mock.return_value = True
  129. isdir_mock.return_value = True
  130. main.perform_prestart_checks(None)
  131. self.assertTrue(exit_mock.called)
  132. isfile_mock.reset_mock()
  133. isdir_mock.reset_mock()
  134. exit_mock.reset_mock()
  135. # Trying case if agent prefix dir does not exist
  136. isfile_mock.return_value = False
  137. isdir_mock.return_value = False
  138. main.perform_prestart_checks(None)
  139. self.assertTrue(exit_mock.called)
  140. isfile_mock.reset_mock()
  141. isdir_mock.reset_mock()
  142. exit_mock.reset_mock()
  143. # Trying normal case
  144. isfile_mock.return_value = False
  145. isdir_mock.return_value = True
  146. main.perform_prestart_checks(None)
  147. self.assertFalse(exit_mock.called)
  148. @patch("time.sleep")
  149. @patch("os.kill")
  150. @patch("os._exit")
  151. @patch("os.path.exists")
  152. def test_daemonize_and_stop(self, exists_mock, _exit_mock, kill_mock, sleep_mock):
  153. oldpid = ProcessHelper.pidfile
  154. pid = str(os.getpid())
  155. _, tmpoutfile = tempfile.mkstemp()
  156. ProcessHelper.pidfile = tmpoutfile
  157. # Test daemonization
  158. main.daemonize()
  159. saved = open(ProcessHelper.pidfile, 'r').read()
  160. self.assertEqual(pid, saved)
  161. # Reuse pid file when testing agent stop
  162. # Testing normal exit
  163. exists_mock.return_value = False
  164. main.stop_agent()
  165. kill_mock.assert_called_with(int(pid), signal.SIGTERM)
  166. _exit_mock.assert_called_with(0)
  167. # Restore
  168. kill_mock.reset_mock()
  169. _exit_mock.reset_mock()
  170. # Testing exit when failed to remove pid file
  171. exists_mock.return_value = True
  172. main.stop_agent()
  173. kill_mock.assert_any_call(int(pid), signal.SIGTERM)
  174. kill_mock.assert_any_call(int(pid), signal.SIGKILL)
  175. _exit_mock.assert_called_with(1)
  176. # Restore
  177. ProcessHelper.pidfile = oldpid
  178. os.remove(tmpoutfile)
  179. @patch.object(main, "setup_logging")
  180. @patch.object(main, "bind_signal_handlers")
  181. @patch.object(main, "stop_agent")
  182. @patch.object(main, "resolve_ambari_config")
  183. @patch.object(main, "perform_prestart_checks")
  184. @patch.object(main, "daemonize")
  185. @patch.object(main, "update_log_level")
  186. @patch.object(NetUtil.NetUtil, "try_to_connect")
  187. @patch.object(Controller, "__init__")
  188. @patch.object(Controller, "start")
  189. @patch.object(Controller, "join")
  190. @patch("optparse.OptionParser.parse_args")
  191. @patch.object(DataCleaner,"start")
  192. @patch.object(DataCleaner,"__init__")
  193. @patch.object(PingPortListener,"start")
  194. @patch.object(PingPortListener,"__init__")
  195. def test_main(self, ping_port_init_mock, ping_port_start_mock, data_clean_init_mock,data_clean_start_mock,
  196. parse_args_mock, join_mock, start_mock, Controller_init_mock, try_to_connect_mock,
  197. update_log_level_mock, daemonize_mock, perform_prestart_checks_mock,
  198. resolve_ambari_config_mock, stop_mock, bind_signal_handlers_mock, setup_logging_mock):
  199. data_clean_init_mock.return_value = None
  200. Controller_init_mock.return_value = None
  201. ping_port_init_mock.return_value = None
  202. options = MagicMock()
  203. parse_args_mock.return_value = (options, MagicMock)
  204. #testing call without command-line arguments
  205. main.main()
  206. self.assertTrue(setup_logging_mock.called)
  207. self.assertTrue(bind_signal_handlers_mock.called)
  208. self.assertTrue(stop_mock.called)
  209. self.assertTrue(resolve_ambari_config_mock.called)
  210. self.assertTrue(perform_prestart_checks_mock.called)
  211. self.assertTrue(daemonize_mock.called)
  212. self.assertTrue(update_log_level_mock.called)
  213. try_to_connect_mock.assert_called_once_with(ANY, -1, ANY)
  214. self.assertTrue(start_mock.called)
  215. self.assertTrue(data_clean_init_mock.called)
  216. self.assertTrue(data_clean_start_mock.called)
  217. self.assertTrue(ping_port_init_mock.called)
  218. self.assertTrue(ping_port_start_mock.called)
  219. perform_prestart_checks_mock.reset_mock()
  220. # Testing call with --expected-hostname parameter
  221. options.expected_hostname = "test.hst"
  222. main.main()
  223. perform_prestart_checks_mock.assert_called_once_with(options.expected_hostname)