aboutsummaryrefslogtreecommitdiff
path: root/bestflags/builder_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'bestflags/builder_test.py')
-rw-r--r--bestflags/builder_test.py158
1 files changed, 140 insertions, 18 deletions
diff --git a/bestflags/builder_test.py b/bestflags/builder_test.py
index 9a636ff3..a705ee1a 100644
--- a/bestflags/builder_test.py
+++ b/bestflags/builder_test.py
@@ -1,42 +1,164 @@
-"""Builder unittest."""
+"""Builder unittest.
+
+This module tests the build helper method and the worker method.
+"""
__author__ = 'yuhenglong@google.com (Yuheng Long)'
+import multiprocessing
+import random
+import sys
import unittest
import builder
+import pipeline_process
+
+
+def MockTaskCostGenerator():
+ """Calls a random number generator and returns a negative number."""
+ return random.randint(-sys.maxint - 1, -1)
+
+
+class MockTask(object):
+ """This class emulates an actual task.
+
+ It does not do the actual compile, but simply returns the build result as when
+ this task is constructed.
+ """
+
+ def __init__(self, flags, cost):
+ """Set up the compile results for this task.
+
+ Args:
+ flags: the optimization flags of this task.
+ cost: the mork build cost of this task.
+
+ The _pre_cost field stored the 'compiled' cost. Once this task is
+ compiled, i.e., by calling the compile method , the _cost field will have
+ this 'compiled' cost.
+ """
+
+ self._flags = flags
+ self._pre_cost = cost
+
+ def get_flags(self):
+ return self._flags
+
+ def __eq__(self, other):
+ if isinstance(other, MockTask):
+ return self._flags == other._flags and self._cost == other._cost
+ return False
+
+ def set_build_result(self, cost):
+ self._cost = cost
+
+ def compile(self):
+ self._cost = self._pre_cost
+
+ def get_build_result(self):
+ return self._cost
+
+ def compiled(self):
+ """Indicates whether the task has been compiled."""
+
+ return '_cost' in self.__dict__
class BuilderTest(unittest.TestCase):
- """This class test the Builder.
+ """This class tests the Builder.
Given the same flags set, the image and the cost should result the same from
the builder.
"""
- def setUp(self):
- """Create the Builder to be tested."""
-
- self.builder = builder.Builder(1, None)
-
- def testCompile(self):
- """"Test the build method.
+ def testHelper(self):
+ """"Test the build helper.
Call the build method twice, and test the results. The results should be the
- same, i.e., the image, the cost and the checksum should be the same.
- Either the compile method or the set_compile_result of the input Generation
- for the Builder should be called, but not both.
+ same, i.e., the cost should be the same.
"""
- self.builder.build(self)
- def testInit(self):
- """"Test the init method.
+ # Set up the input, helper and output queue for the worker method.
+ manager = multiprocessing.Manager()
+ helper_queue = manager.Queue()
+ output_queue = manager.Queue()
+ built_queue = manager.Queue()
+
+ # Set up the helper process that holds the helper method.
+ helper_process = multiprocessing.Process(target=builder.build_helper,
+ args=({}, helper_queue,
+ built_queue, output_queue))
+ helper_process.start()
+
+ # A dictionary defines the mock compile result to the build_helper.
+ mock_compile_result = {1: 1995, 2: 59, 9: 1027}
+
+ # Test if there is a task that is done before, whether the duplicate task
+ # will have the same result. Here, two different scenarios are tested. That
+ # is the mock results are added to the built_queue before and after the
+ # corresponding mock tasks being ;added to the input queue.
+ built_queue.put((9, mock_compile_result[9]))
+
+ # The output of the helper should contain all the following tasks.
+ results = [1, 1, 2, 9]
+
+ # Testing the correctness of having tasks having the same flags key, here 1.
+ for result in results:
+ helper_queue.put(MockTask(result, MockTaskCostGenerator()))
+
+ built_queue.put((2, mock_compile_result[2]))
+ built_queue.put((1, mock_compile_result[1]))
+
+ # Signal there is no more duplicate task.
+ helper_queue.put(pipeline_process.POISONPILL)
+ helper_process.join()
- If a certain flag set has been encountered before, the builder should not
- recompile the image with the same optimization flag set.
+ while results:
+ task = output_queue.get()
+ flags = task._flags
+ cost = task._cost
+ self.assertTrue(flags in results)
+ if flags in mock_compile_result:
+ self.assertTrue(cost, mock_compile_result[flags])
+ results.remove(task._flags)
+
+ def testWorker(self):
+ """"Test the actual build worker method.
+
+ The worker should process all the input tasks and output the tasks to the
+ helper and result queue.
"""
- pass
+ manager = multiprocessing.Manager()
+ output_queue = manager.Queue()
+ built_queue = manager.Queue()
+
+ # A dictionary defines the mock tasks and their corresponding compile
+ # results.
+ mock_compile_tasks = {1: 86, 2: 788}
+
+ mock_tasks = []
+
+ for flag, cost in mock_compile_tasks.iteritems():
+ mock_tasks.append(MockTask(flag, cost))
+
+ # Submit the mock tasks to the build worker.
+ for mock_task in mock_tasks:
+ builder.build_worker(mock_task, built_queue, output_queue)
+
+ # The tasks, from the output queue, should be the same as the input and
+ # should be compiled.
+ for task in mock_tasks:
+ output = output_queue.get()
+ self.assertEqual(output, task)
+ self.assertTrue(output.compiled())
+
+ # The tasks, from the built queue, should be defined in the
+ # mock_compile_tasks dictionary.
+ for flag, cost in mock_compile_tasks.iteritems():
+ helper_input = built_queue.get()
+ self.assertEqual(helper_input, (flag, cost))
+
if __name__ == '__main__':
unittest.main()