Home | History | Annotate | Download | only in base
      1 # Copyright 2013 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """Unittests for test_dispatcher.py."""
      6 
      7 import os
      8 import sys
      9 import unittest
     10 
     11 sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)),
     12                 os.pardir, os.pardir))
     13 
     14 # Mock out android_commands.GetAttachedDevices().
     15 from pylib import android_commands
     16 android_commands.GetAttachedDevices = lambda: ['0', '1']
     17 from pylib import constants
     18 from pylib.utils import watchdog_timer
     19 
     20 import base_test_result
     21 import test_dispatcher
     22 
     23 
     24 class TestException(Exception):
     25   pass
     26 
     27 
     28 class MockRunner(object):
     29   """A mock TestRunner."""
     30   def __init__(self, device='0', shard_index=0):
     31     self.device = device
     32     self.shard_index = shard_index
     33     self.setups = 0
     34     self.teardowns = 0
     35 
     36   def RunTest(self, test):
     37     results = base_test_result.TestRunResults()
     38     results.AddResult(
     39         base_test_result.BaseTestResult(test, base_test_result.ResultType.PASS))
     40     return (results, None)
     41 
     42   def SetUp(self):
     43     self.setups += 1
     44 
     45   def TearDown(self):
     46     self.teardowns += 1
     47 
     48 
     49 class MockRunnerFail(MockRunner):
     50   def RunTest(self, test):
     51     results = base_test_result.TestRunResults()
     52     results.AddResult(
     53         base_test_result.BaseTestResult(test, base_test_result.ResultType.FAIL))
     54     return (results, test)
     55 
     56 
     57 class MockRunnerFailTwice(MockRunner):
     58   def __init__(self, device='0', shard_index=0):
     59     super(MockRunnerFailTwice, self).__init__(device, shard_index)
     60     self._fails = 0
     61 
     62   def RunTest(self, test):
     63     self._fails += 1
     64     results = base_test_result.TestRunResults()
     65     if self._fails <= 2:
     66       results.AddResult(base_test_result.BaseTestResult(
     67           test, base_test_result.ResultType.FAIL))
     68       return (results, test)
     69     else:
     70       results.AddResult(base_test_result.BaseTestResult(
     71           test, base_test_result.ResultType.PASS))
     72       return (results, None)
     73 
     74 
     75 class MockRunnerException(MockRunner):
     76   def RunTest(self, test):
     77     raise TestException
     78 
     79 
     80 class TestFunctions(unittest.TestCase):
     81   """Tests test_dispatcher._RunTestsFromQueue."""
     82   @staticmethod
     83   def _RunTests(mock_runner, tests):
     84     results = []
     85     tests = test_dispatcher._TestCollection(
     86         [test_dispatcher._Test(t) for t in tests])
     87     test_dispatcher._RunTestsFromQueue(mock_runner, tests, results,
     88                                        watchdog_timer.WatchdogTimer(None), 2)
     89     run_results = base_test_result.TestRunResults()
     90     for r in results:
     91       run_results.AddTestRunResults(r)
     92     return run_results
     93 
     94   def testRunTestsFromQueue(self):
     95     results = TestFunctions._RunTests(MockRunner(), ['a', 'b'])
     96     self.assertEqual(len(results.GetPass()), 2)
     97     self.assertEqual(len(results.GetNotPass()), 0)
     98 
     99   def testRunTestsFromQueueRetry(self):
    100     results = TestFunctions._RunTests(MockRunnerFail(), ['a', 'b'])
    101     self.assertEqual(len(results.GetPass()), 0)
    102     self.assertEqual(len(results.GetFail()), 2)
    103 
    104   def testRunTestsFromQueueFailTwice(self):
    105     results = TestFunctions._RunTests(MockRunnerFailTwice(), ['a', 'b'])
    106     self.assertEqual(len(results.GetPass()), 2)
    107     self.assertEqual(len(results.GetNotPass()), 0)
    108 
    109   def testSetUp(self):
    110     runners = []
    111     counter = test_dispatcher._ThreadSafeCounter()
    112     test_dispatcher._SetUp(MockRunner, '0', runners, counter)
    113     self.assertEqual(len(runners), 1)
    114     self.assertEqual(runners[0].setups, 1)
    115 
    116   def testThreadSafeCounter(self):
    117     counter = test_dispatcher._ThreadSafeCounter()
    118     for i in xrange(5):
    119       self.assertEqual(counter.GetAndIncrement(), i)
    120 
    121 
    122 class TestThreadGroupFunctions(unittest.TestCase):
    123   """Tests test_dispatcher._RunAllTests and test_dispatcher._CreateRunners."""
    124   def setUp(self):
    125     self.tests = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
    126     shared_test_collection = test_dispatcher._TestCollection(
    127         [test_dispatcher._Test(t) for t in self.tests])
    128     self.test_collection_factory = lambda: shared_test_collection
    129 
    130   def testCreate(self):
    131     runners = test_dispatcher._CreateRunners(MockRunner, ['0', '1'])
    132     for runner in runners:
    133       self.assertEqual(runner.setups, 1)
    134     self.assertEqual(set([r.device for r in runners]),
    135                      set(['0', '1']))
    136     self.assertEqual(set([r.shard_index for r in runners]),
    137                      set([0, 1]))
    138 
    139   def testRun(self):
    140     runners = [MockRunner('0'), MockRunner('1')]
    141     results, exit_code = test_dispatcher._RunAllTests(
    142         runners, self.test_collection_factory, 0)
    143     self.assertEqual(len(results.GetPass()), len(self.tests))
    144     self.assertEqual(exit_code, 0)
    145 
    146   def testTearDown(self):
    147     runners = [MockRunner('0'), MockRunner('1')]
    148     test_dispatcher._TearDownRunners(runners)
    149     for runner in runners:
    150       self.assertEqual(runner.teardowns, 1)
    151 
    152   def testRetry(self):
    153     runners = test_dispatcher._CreateRunners(MockRunnerFail, ['0', '1'])
    154     results, exit_code = test_dispatcher._RunAllTests(
    155         runners, self.test_collection_factory, 0)
    156     self.assertEqual(len(results.GetFail()), len(self.tests))
    157     self.assertEqual(exit_code, constants.ERROR_EXIT_CODE)
    158 
    159   def testReraise(self):
    160     runners = test_dispatcher._CreateRunners(MockRunnerException, ['0', '1'])
    161     with self.assertRaises(TestException):
    162       test_dispatcher._RunAllTests(runners, self.test_collection_factory, 0)
    163 
    164 
    165 class TestShard(unittest.TestCase):
    166   """Tests test_dispatcher.RunTests with sharding."""
    167   @staticmethod
    168   def _RunShard(runner_factory):
    169     return test_dispatcher.RunTests(
    170         ['a', 'b', 'c'], runner_factory, False, None, shard=True)
    171 
    172   def testShard(self):
    173     results, exit_code = TestShard._RunShard(MockRunner)
    174     self.assertEqual(len(results.GetPass()), 3)
    175     self.assertEqual(exit_code, 0)
    176 
    177   def testFailing(self):
    178     results, exit_code = TestShard._RunShard(MockRunnerFail)
    179     self.assertEqual(len(results.GetPass()), 0)
    180     self.assertEqual(len(results.GetFail()), 3)
    181     self.assertEqual(exit_code, constants.ERROR_EXIT_CODE)
    182 
    183   def testNoTests(self):
    184     results, exit_code = test_dispatcher.RunTests(
    185         [], MockRunner, False, None, shard=True)
    186     self.assertEqual(len(results.GetAll()), 0)
    187     self.assertEqual(exit_code, constants.ERROR_EXIT_CODE)
    188 
    189 
    190 class TestReplicate(unittest.TestCase):
    191   """Tests test_dispatcher.RunTests with replication."""
    192   @staticmethod
    193   def _RunReplicate(runner_factory):
    194     return test_dispatcher.RunTests(
    195         ['a', 'b', 'c'], runner_factory, False, None, shard=False)
    196 
    197   def testReplicate(self):
    198     results, exit_code = TestReplicate._RunReplicate(MockRunner)
    199     # We expect 6 results since each test should have been run on every device
    200     self.assertEqual(len(results.GetPass()), 6)
    201     self.assertEqual(exit_code, 0)
    202 
    203   def testFailing(self):
    204     results, exit_code = TestReplicate._RunReplicate(MockRunnerFail)
    205     self.assertEqual(len(results.GetPass()), 0)
    206     self.assertEqual(len(results.GetFail()), 6)
    207     self.assertEqual(exit_code, constants.ERROR_EXIT_CODE)
    208 
    209   def testNoTests(self):
    210     results, exit_code = test_dispatcher.RunTests(
    211         [], MockRunner, False, None, shard=False)
    212     self.assertEqual(len(results.GetAll()), 0)
    213     self.assertEqual(exit_code, constants.ERROR_EXIT_CODE)
    214 
    215 
    216 if __name__ == '__main__':
    217   unittest.main()
    218