PageRenderTime 60ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/external/webkit/Tools/Scripts/webkitpy/layout_tests/layout_package/manager_worker_broker_unittest.py

https://gitlab.com/brian0218/rk3188_r-box_android4.2.2_sdk
Python | 289 lines | 241 code | 16 blank | 32 comment | 4 complexity | 1d4c9ad77be07fbc38aa945ca256cf1a MD5 | raw file
  1. # Copyright (C) 2010 Google Inc. All rights reserved.
  2. #
  3. # Redistribution and use in source and binary forms, with or without
  4. # modification, are permitted provided that the following conditions are
  5. # met:
  6. #
  7. # * Redistributions of source code must retain the above copyright
  8. # notice, this list of conditions and the following disclaimer.
  9. # * Redistributions in binary form must reproduce the above
  10. # copyright notice, this list of conditions and the following disclaimer
  11. # in the documentation and/or other materials provided with the
  12. # distribution.
  13. # * Neither the name of Google Inc. nor the names of its
  14. # contributors may be used to endorse or promote products derived from
  15. # this software without specific prior written permission.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  20. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  21. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  23. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  27. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. import optparse
  29. import Queue
  30. import sys
  31. import unittest
  32. try:
  33. import multiprocessing
  34. except ImportError:
  35. multiprocessing = None
  36. from webkitpy.common.system import outputcapture
  37. from webkitpy.layout_tests import port
  38. from webkitpy.layout_tests.layout_package import manager_worker_broker
  39. from webkitpy.layout_tests.layout_package import message_broker2
  40. from webkitpy.layout_tests.layout_package import printing
  41. # In order to reliably control when child workers are starting and stopping,
  42. # we use a pair of global variables to hold queues used for messaging. Ideally
  43. # we wouldn't need globals, but we can't pass these through a lexical closure
  44. # because those can't be Pickled and sent to a subprocess, and we'd prefer not
  45. # to have to pass extra arguments to the worker in the start_worker() call.
  46. starting_queue = None
  47. stopping_queue = None
  48. def make_broker(manager, worker_model, start_queue=None, stop_queue=None):
  49. global starting_queue
  50. global stopping_queue
  51. starting_queue = start_queue
  52. stopping_queue = stop_queue
  53. options = get_options(worker_model)
  54. return manager_worker_broker.get(port.get("test"), options, manager, _TestWorker)
  55. class _TestWorker(manager_worker_broker.AbstractWorker):
  56. def __init__(self, broker_connection, worker_number, options):
  57. self._broker_connection = broker_connection
  58. self._options = options
  59. self._worker_number = worker_number
  60. self._name = 'TestWorker/%d' % worker_number
  61. self._stopped = False
  62. self._canceled = False
  63. self._starting_queue = starting_queue
  64. self._stopping_queue = stopping_queue
  65. def handle_stop(self, src):
  66. self._stopped = True
  67. def handle_test(self, src, an_int, a_str):
  68. assert an_int == 1
  69. assert a_str == "hello, world"
  70. self._broker_connection.post_message('test', 2, 'hi, everybody')
  71. def is_done(self):
  72. return self._stopped or self._canceled
  73. def name(self):
  74. return self._name
  75. def cancel(self):
  76. self._canceled = True
  77. def run(self, port):
  78. if self._starting_queue:
  79. self._starting_queue.put('')
  80. if self._stopping_queue:
  81. self._stopping_queue.get()
  82. try:
  83. self._broker_connection.run_message_loop()
  84. self._broker_connection.yield_to_broker()
  85. self._broker_connection.post_message('done')
  86. except Exception, e:
  87. self._broker_connection.post_message('exception', (type(e), str(e), None))
  88. def get_options(worker_model):
  89. option_list = (manager_worker_broker.runtime_options() +
  90. printing.print_options() +
  91. [optparse.make_option("--experimental-fully-parallel", default=False),
  92. optparse.make_option("--child-processes", default='2')])
  93. parser = optparse.OptionParser(option_list=option_list)
  94. options, args = parser.parse_args(args=['--worker-model', worker_model])
  95. return options
  96. class FunctionTests(unittest.TestCase):
  97. def test_get__inline(self):
  98. self.assertTrue(make_broker(self, 'inline') is not None)
  99. def test_get__threads(self):
  100. self.assertTrue(make_broker(self, 'threads') is not None)
  101. def test_get__processes(self):
  102. # This test sometimes fails on Windows. See <http://webkit.org/b/55087>.
  103. if sys.platform in ('cygwin', 'win32'):
  104. return
  105. if multiprocessing:
  106. self.assertTrue(make_broker(self, 'processes') is not None)
  107. else:
  108. self.assertRaises(ValueError, make_broker, self, 'processes')
  109. def test_get__unknown(self):
  110. self.assertRaises(ValueError, make_broker, self, 'unknown')
  111. class _TestsMixin(object):
  112. """Mixin class that implements a series of tests to enforce the
  113. contract all implementations must follow."""
  114. def name(self):
  115. return 'Tester'
  116. def is_done(self):
  117. return self._done
  118. def handle_done(self, src):
  119. self._done = True
  120. def handle_test(self, src, an_int, a_str):
  121. self._an_int = an_int
  122. self._a_str = a_str
  123. def handle_exception(self, src, exc_info):
  124. self._exception = exc_info
  125. self._done = True
  126. def setUp(self):
  127. self._an_int = None
  128. self._a_str = None
  129. self._broker = None
  130. self._done = False
  131. self._exception = None
  132. self._worker_model = None
  133. def make_broker(self, starting_queue=None, stopping_queue=None):
  134. self._broker = make_broker(self, self._worker_model, starting_queue,
  135. stopping_queue)
  136. def test_cancel(self):
  137. self.make_broker()
  138. worker = self._broker.start_worker(0)
  139. worker.cancel()
  140. self._broker.post_message('test', 1, 'hello, world')
  141. worker.join(0.5)
  142. self.assertFalse(worker.is_alive())
  143. def test_done(self):
  144. self.make_broker()
  145. worker = self._broker.start_worker(0)
  146. self._broker.post_message('test', 1, 'hello, world')
  147. self._broker.post_message('stop')
  148. self._broker.run_message_loop()
  149. worker.join(0.5)
  150. self.assertFalse(worker.is_alive())
  151. self.assertTrue(self.is_done())
  152. self.assertEqual(self._an_int, 2)
  153. self.assertEqual(self._a_str, 'hi, everybody')
  154. def test_log_wedged_worker(self):
  155. starting_queue = self.queue()
  156. stopping_queue = self.queue()
  157. self.make_broker(starting_queue, stopping_queue)
  158. oc = outputcapture.OutputCapture()
  159. oc.capture_output()
  160. try:
  161. worker = self._broker.start_worker(0)
  162. starting_queue.get()
  163. worker.log_wedged_worker('test_name')
  164. stopping_queue.put('')
  165. self._broker.post_message('stop')
  166. self._broker.run_message_loop()
  167. worker.join(0.5)
  168. self.assertFalse(worker.is_alive())
  169. self.assertTrue(self.is_done())
  170. finally:
  171. oc.restore_output()
  172. def test_unknown_message(self):
  173. self.make_broker()
  174. worker = self._broker.start_worker(0)
  175. self._broker.post_message('unknown')
  176. self._broker.run_message_loop()
  177. worker.join(0.5)
  178. self.assertTrue(self.is_done())
  179. self.assertFalse(worker.is_alive())
  180. self.assertEquals(self._exception[0], ValueError)
  181. self.assertEquals(self._exception[1],
  182. "TestWorker/0: received message 'unknown' it couldn't handle")
  183. class InlineBrokerTests(_TestsMixin, unittest.TestCase):
  184. def setUp(self):
  185. _TestsMixin.setUp(self)
  186. self._worker_model = 'inline'
  187. def test_log_wedged_worker(self):
  188. self.make_broker()
  189. worker = self._broker.start_worker(0)
  190. self.assertRaises(AssertionError, worker.log_wedged_worker, None)
  191. # FIXME: https://bugs.webkit.org/show_bug.cgi?id=54520.
  192. if multiprocessing and sys.platform not in ('cygwin', 'win32'):
  193. class MultiProcessBrokerTests(_TestsMixin, unittest.TestCase):
  194. def setUp(self):
  195. _TestsMixin.setUp(self)
  196. self._worker_model = 'processes'
  197. def queue(self):
  198. return multiprocessing.Queue()
  199. class ThreadedBrokerTests(_TestsMixin, unittest.TestCase):
  200. def setUp(self):
  201. _TestsMixin.setUp(self)
  202. self._worker_model = 'threads'
  203. def queue(self):
  204. return Queue.Queue()
  205. class FunctionsTest(unittest.TestCase):
  206. def test_runtime_options(self):
  207. option_list = manager_worker_broker.runtime_options()
  208. parser = optparse.OptionParser(option_list=option_list)
  209. options, args = parser.parse_args([])
  210. self.assertTrue(options)
  211. class InterfaceTest(unittest.TestCase):
  212. # These tests mostly exist to pacify coverage.
  213. # FIXME: There must be a better way to do this and also verify
  214. # that classes do implement every abstract method in an interface.
  215. def test_managerconnection_is_abstract(self):
  216. # Test that all the base class methods are abstract and have the
  217. # signature we expect.
  218. broker = make_broker(self, 'inline')
  219. obj = manager_worker_broker._ManagerConnection(broker._broker, None, self, None)
  220. self.assertRaises(NotImplementedError, obj.start_worker, 0)
  221. def test_workerconnection_is_abstract(self):
  222. # Test that all the base class methods are abstract and have the
  223. # signature we expect.
  224. broker = make_broker(self, 'inline')
  225. obj = manager_worker_broker._WorkerConnection(broker._broker, _TestWorker, 0, None)
  226. self.assertRaises(NotImplementedError, obj.cancel)
  227. self.assertRaises(NotImplementedError, obj.is_alive)
  228. self.assertRaises(NotImplementedError, obj.join, None)
  229. self.assertRaises(NotImplementedError, obj.log_wedged_worker, None)
  230. if __name__ == '__main__':
  231. unittest.main()