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