summaryrefslogtreecommitdiffstats
path: root/Tools/Scripts/webkitpy/layout_tests/layout_package/manager_worker_broker_unittest.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/Scripts/webkitpy/layout_tests/layout_package/manager_worker_broker_unittest.py')
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/layout_package/manager_worker_broker_unittest.py227
1 files changed, 227 insertions, 0 deletions
diff --git a/Tools/Scripts/webkitpy/layout_tests/layout_package/manager_worker_broker_unittest.py b/Tools/Scripts/webkitpy/layout_tests/layout_package/manager_worker_broker_unittest.py
new file mode 100644
index 0000000..ffbe081
--- /dev/null
+++ b/Tools/Scripts/webkitpy/layout_tests/layout_package/manager_worker_broker_unittest.py
@@ -0,0 +1,227 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import optparse
+import Queue
+import sys
+import unittest
+
+try:
+ import multiprocessing
+except ImportError:
+ multiprocessing = None
+
+
+from webkitpy.common.system import outputcapture
+
+from webkitpy.layout_tests import port
+from webkitpy.layout_tests.layout_package import manager_worker_broker
+from webkitpy.layout_tests.layout_package import message_broker2
+
+
+class TestWorker(manager_worker_broker.AbstractWorker):
+ def __init__(self, broker_connection, worker_number, options):
+ self._broker_connection = broker_connection
+ self._options = options
+ self._worker_number = worker_number
+ self._name = 'TestWorker/%d' % worker_number
+ self._stopped = False
+
+ def handle_stop(self, src):
+ self._stopped = True
+
+ def handle_test(self, src, an_int, a_str):
+ assert an_int == 1
+ assert a_str == "hello, world"
+ self._broker_connection.post_message('test', 2, 'hi, everybody')
+
+ def is_done(self):
+ return self._stopped
+
+ def name(self):
+ return self._name
+
+ def start(self):
+ pass
+
+ def run(self, port):
+ try:
+ self._broker_connection.run_message_loop()
+ self._broker_connection.yield_to_broker()
+ self._broker_connection.post_message('done')
+ except Exception, e:
+ self._broker_connection.post_message('exception', (type(e), str(e), None))
+
+
+def get_options(worker_model):
+ option_list = manager_worker_broker.runtime_options()
+ parser = optparse.OptionParser(option_list=option_list)
+ options, args = parser.parse_args(args=['--worker-model', worker_model])
+ return options
+
+
+def make_broker(manager, worker_model):
+ options = get_options(worker_model)
+ return manager_worker_broker.get(port.get("test"), options, manager,
+ TestWorker)
+
+
+class FunctionTests(unittest.TestCase):
+ def test_get__inline(self):
+ self.assertTrue(make_broker(self, 'inline') is not None)
+
+ def test_get__threads(self):
+ self.assertTrue(make_broker(self, 'threads') is not None)
+
+ def test_get__processes(self):
+ if multiprocessing:
+ self.assertTrue(make_broker(self, 'processes') is not None)
+ else:
+ self.assertRaises(ValueError, make_broker, self, 'processes')
+
+ def test_get__unknown(self):
+ self.assertRaises(ValueError, make_broker, self, 'unknown')
+
+
+class _TestsMixin(object):
+ """Mixin class that implements a series of tests to enforce the
+ contract all implementations must follow."""
+
+ #
+ # Methods to implement the Manager side of the ClientInterface
+ #
+ def name(self):
+ return 'Tester'
+
+ def is_done(self):
+ return self._done
+
+ #
+ # Handlers for the messages the TestWorker may send.
+ #
+ def handle_done(self, src):
+ self._done = True
+
+ def handle_test(self, src, an_int, a_str):
+ self._an_int = an_int
+ self._a_str = a_str
+
+ def handle_exception(self, src, exc_info):
+ self._exception = exc_info
+ self._done = True
+
+ #
+ # Testing helper methods
+ #
+ def setUp(self):
+ self._an_int = None
+ self._a_str = None
+ self._broker = None
+ self._done = False
+ self._exception = None
+ self._worker_model = None
+
+ def make_broker(self):
+ self._broker = make_broker(self, self._worker_model)
+
+ #
+ # Actual unit tests
+ #
+ def test_done(self):
+ if not self._worker_model:
+ return
+ self.make_broker()
+ worker = self._broker.start_worker(0)
+ self._broker.post_message('test', 1, 'hello, world')
+ self._broker.post_message('stop')
+ self._broker.run_message_loop()
+ self.assertTrue(self.is_done())
+ self.assertEqual(self._an_int, 2)
+ self.assertEqual(self._a_str, 'hi, everybody')
+
+ def test_unknown_message(self):
+ if not self._worker_model:
+ return
+ self.make_broker()
+ worker = self._broker.start_worker(0)
+ self._broker.post_message('unknown')
+ self._broker.run_message_loop()
+
+ self.assertTrue(self.is_done())
+ self.assertEquals(self._exception[0], ValueError)
+ self.assertEquals(self._exception[1],
+ "TestWorker/0: received message 'unknown' it couldn't handle")
+
+
+class InlineBrokerTests(_TestsMixin, unittest.TestCase):
+ def setUp(self):
+ _TestsMixin.setUp(self)
+ self._worker_model = 'inline'
+
+
+class MultiProcessBrokerTests(_TestsMixin, unittest.TestCase):
+ def setUp(self):
+ _TestsMixin.setUp(self)
+ if multiprocessing:
+ self._worker_model = 'processes'
+ else:
+ self._worker_model = None
+
+ def queue(self):
+ return multiprocessing.Queue()
+
+
+class ThreadedBrokerTests(_TestsMixin, unittest.TestCase):
+ def setUp(self):
+ _TestsMixin.setUp(self)
+ self._worker_model = 'threads'
+
+
+class FunctionsTest(unittest.TestCase):
+ def test_runtime_options(self):
+ option_list = manager_worker_broker.runtime_options()
+ parser = optparse.OptionParser(option_list=option_list)
+ options, args = parser.parse_args([])
+ self.assertTrue(options)
+
+
+class InterfaceTest(unittest.TestCase):
+ # These tests mostly exist to pacify coverage.
+
+ # FIXME: There must be a better way to do this and also verify
+ # that classes do implement every abstract method in an interface.
+ def test_managerconnection_is_abstract(self):
+ # Test that all the base class methods are abstract and have the
+ # signature we expect.
+ broker = make_broker(self, 'inline')
+ obj = manager_worker_broker._ManagerConnection(broker._broker, None, self, None)
+ self.assertRaises(NotImplementedError, obj.start_worker, 0)
+
+
+if __name__ == '__main__':
+ unittest.main()