xref: /aosp_15_r20/external/toolchain-utils/bestflags/pipeline_worker_test.py (revision 760c253c1ed00ce9abd48f8546f08516e57485fe)
1*760c253cSXin Li# Copyright 2013 The ChromiumOS Authors
2*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be
3*760c253cSXin Li# found in the LICENSE file.
4*760c253cSXin Li"""Unittest for the pipeline_worker functions in the build/test stage.
5*760c253cSXin Li
6*760c253cSXin LiPart of the Chrome build flags optimization.
7*760c253cSXin Li
8*760c253cSXin LiThis module tests the helper method and the worker method.
9*760c253cSXin Li"""
10*760c253cSXin Li
11*760c253cSXin Li__author__ = "[email protected] (Yuheng Long)"
12*760c253cSXin Li
13*760c253cSXin Liimport multiprocessing
14*760c253cSXin Liimport random
15*760c253cSXin Liimport sys
16*760c253cSXin Liimport unittest
17*760c253cSXin Li
18*760c253cSXin Lifrom mock_task import MockTask
19*760c253cSXin Liimport pipeline_process
20*760c253cSXin Liimport pipeline_worker
21*760c253cSXin Li
22*760c253cSXin Li
23*760c253cSXin Li# Pick an integer at random.
24*760c253cSXin LiTEST_STAGE = -3
25*760c253cSXin Li
26*760c253cSXin Li
27*760c253cSXin Lidef MockTaskCostGenerator():
28*760c253cSXin Li    """Calls a random number generator and returns a negative number."""
29*760c253cSXin Li    return random.randint(-sys.maxint - 1, -1)
30*760c253cSXin Li
31*760c253cSXin Li
32*760c253cSXin Liclass PipelineWorkerTest(unittest.TestCase):
33*760c253cSXin Li    """This class tests the pipeline_worker functions.
34*760c253cSXin Li
35*760c253cSXin Li    Given the same identifier, the cost should result the same from the
36*760c253cSXin Li    pipeline_worker functions.
37*760c253cSXin Li    """
38*760c253cSXin Li
39*760c253cSXin Li    def testHelper(self):
40*760c253cSXin Li        """ "Test the helper.
41*760c253cSXin Li
42*760c253cSXin Li        Call the helper method twice, and test the results. The results should be
43*760c253cSXin Li        the same, i.e., the cost should be the same.
44*760c253cSXin Li        """
45*760c253cSXin Li
46*760c253cSXin Li        # Set up the input, helper and output queue for the helper method.
47*760c253cSXin Li        manager = multiprocessing.Manager()
48*760c253cSXin Li        helper_queue = manager.Queue()
49*760c253cSXin Li        result_queue = manager.Queue()
50*760c253cSXin Li        completed_queue = manager.Queue()
51*760c253cSXin Li
52*760c253cSXin Li        # Set up the helper process that holds the helper method.
53*760c253cSXin Li        helper_process = multiprocessing.Process(
54*760c253cSXin Li            target=pipeline_worker.Helper,
55*760c253cSXin Li            args=(TEST_STAGE, {}, helper_queue, completed_queue, result_queue),
56*760c253cSXin Li        )
57*760c253cSXin Li        helper_process.start()
58*760c253cSXin Li
59*760c253cSXin Li        # A dictionary defines the mock result to the helper.
60*760c253cSXin Li        mock_result = {1: 1995, 2: 59, 9: 1027}
61*760c253cSXin Li
62*760c253cSXin Li        # Test if there is a task that is done before, whether the duplicate task
63*760c253cSXin Li        # will have the same result. Here, two different scenarios are tested. That
64*760c253cSXin Li        # is the mock results are added to the completed_queue before and after the
65*760c253cSXin Li        # corresponding mock tasks being added to the input queue.
66*760c253cSXin Li        completed_queue.put((9, mock_result[9]))
67*760c253cSXin Li
68*760c253cSXin Li        # The output of the helper should contain all the following tasks.
69*760c253cSXin Li        results = [1, 1, 2, 9]
70*760c253cSXin Li
71*760c253cSXin Li        # Testing the correctness of having tasks having the same identifier, here
72*760c253cSXin Li        # 1.
73*760c253cSXin Li        for result in results:
74*760c253cSXin Li            helper_queue.put(
75*760c253cSXin Li                MockTask(TEST_STAGE, result, MockTaskCostGenerator())
76*760c253cSXin Li            )
77*760c253cSXin Li
78*760c253cSXin Li        completed_queue.put((2, mock_result[2]))
79*760c253cSXin Li        completed_queue.put((1, mock_result[1]))
80*760c253cSXin Li
81*760c253cSXin Li        # Signal there is no more duplicate task.
82*760c253cSXin Li        helper_queue.put(pipeline_process.POISONPILL)
83*760c253cSXin Li        helper_process.join()
84*760c253cSXin Li
85*760c253cSXin Li        while results:
86*760c253cSXin Li            task = result_queue.get()
87*760c253cSXin Li            identifier = task.GetIdentifier(TEST_STAGE)
88*760c253cSXin Li            self.assertTrue(identifier in results)
89*760c253cSXin Li            if identifier in mock_result:
90*760c253cSXin Li                self.assertTrue(
91*760c253cSXin Li                    task.GetResult(TEST_STAGE), mock_result[identifier]
92*760c253cSXin Li                )
93*760c253cSXin Li            results.remove(identifier)
94*760c253cSXin Li
95*760c253cSXin Li    def testWorker(self):
96*760c253cSXin Li        """ "Test the worker method.
97*760c253cSXin Li
98*760c253cSXin Li        The worker should process all the input tasks and output the tasks to the
99*760c253cSXin Li        helper and result queue.
100*760c253cSXin Li        """
101*760c253cSXin Li
102*760c253cSXin Li        manager = multiprocessing.Manager()
103*760c253cSXin Li        result_queue = manager.Queue()
104*760c253cSXin Li        completed_queue = manager.Queue()
105*760c253cSXin Li
106*760c253cSXin Li        # A dictionary defines the mock tasks and their corresponding results.
107*760c253cSXin Li        mock_work_tasks = {1: 86, 2: 788}
108*760c253cSXin Li
109*760c253cSXin Li        mock_tasks = []
110*760c253cSXin Li
111*760c253cSXin Li        for flag, cost in mock_work_tasks.iteritems():
112*760c253cSXin Li            mock_tasks.append(MockTask(TEST_STAGE, flag, cost))
113*760c253cSXin Li
114*760c253cSXin Li        # Submit the mock tasks to the worker.
115*760c253cSXin Li        for mock_task in mock_tasks:
116*760c253cSXin Li            pipeline_worker.Worker(
117*760c253cSXin Li                TEST_STAGE, mock_task, completed_queue, result_queue
118*760c253cSXin Li            )
119*760c253cSXin Li
120*760c253cSXin Li        # The tasks, from the output queue, should be the same as the input and
121*760c253cSXin Li        # should be performed.
122*760c253cSXin Li        for task in mock_tasks:
123*760c253cSXin Li            output = result_queue.get()
124*760c253cSXin Li            self.assertEqual(output, task)
125*760c253cSXin Li            self.assertTrue(output.Done(TEST_STAGE))
126*760c253cSXin Li
127*760c253cSXin Li        # The tasks, from the completed_queue, should be defined in the
128*760c253cSXin Li        # mock_work_tasks dictionary.
129*760c253cSXin Li        for flag, cost in mock_work_tasks.iteritems():
130*760c253cSXin Li            helper_input = completed_queue.get()
131*760c253cSXin Li            self.assertEqual(helper_input, (flag, cost))
132*760c253cSXin Li
133*760c253cSXin Li
134*760c253cSXin Liif __name__ == "__main__":
135*760c253cSXin Li    unittest.main()
136