Home | History | Annotate | Download | only in dynamic_suite
      1 #!/usr/bin/python
      2 #
      3 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 """Unit tests for server/cros/dynamic_suite/dynamic_suite.py."""
      8 
      9 import mox
     10 import os
     11 import signal
     12 import unittest
     13 
     14 from autotest_lib.client.common_lib import base_job, error
     15 from autotest_lib.client.common_lib.cros import dev_server
     16 from autotest_lib.server.cros import provision
     17 from autotest_lib.server.cros.dynamic_suite import dynamic_suite
     18 from autotest_lib.server.cros.dynamic_suite.suite import Suite
     19 
     20 
     21 class DynamicSuiteTest(mox.MoxTestBase):
     22     """Unit tests for dynamic_suite module methods.
     23 
     24     @var _DARGS: default args to vet.
     25     """
     26 
     27     _DEVSERVER_HOST = 'http://devserver1'
     28     _BUILDS = {provision.CROS_VERSION_PREFIX: 'build_1',
     29                provision.FW_RW_VERSION_PREFIX:'fwrw_build_1'}
     30 
     31     def setUp(self):
     32 
     33         super(DynamicSuiteTest, self).setUp()
     34         self._DARGS = {'name': 'name',
     35                        'builds': self._BUILDS,
     36                        'board': 'board',
     37                        'job': self.mox.CreateMock(base_job.base_job),
     38                        'num': 1,
     39                        'pool': 'pool',
     40                        'check_hosts': False,
     41                        'add_experimental': False,
     42                        'suite_dependencies': ['test_dep'],
     43                        'devserver_url': self._DEVSERVER_HOST}
     44 
     45 
     46 
     47     def testVetRequiredReimageAndRunArgs(self):
     48         """Should verify only that required args are present and correct."""
     49         spec = dynamic_suite.SuiteSpec(**self._DARGS)
     50         self.assertEquals(spec.builds, self._DARGS['builds'])
     51         self.assertEquals(spec.board, 'board:' + self._DARGS['board'])
     52         self.assertEquals(spec.name, self._DARGS['name'])
     53         self.assertEquals(spec.job, self._DARGS['job'])
     54 
     55 
     56     def testVetReimageAndRunBuildArgFail(self):
     57         """Should fail verification if both |builds| and |build| are not set.
     58         """
     59         self._DARGS['build'] = None
     60         self._DARGS['builds'] = None
     61         self.assertRaises(error.SuiteArgumentException,
     62                           dynamic_suite.SuiteSpec,
     63                           **self._DARGS)
     64         self._DARGS['build'] = 'build1'
     65         self._DARGS['builds'] = {'cros-version': 'build2',
     66                                  'firmware-version': 'build3'}
     67         self.assertRaises(error.SuiteArgumentException,
     68                           dynamic_suite.SuiteSpec,
     69                           **self._DARGS)
     70 
     71 
     72     def testVetReimageAndRunBoardArgFail(self):
     73         """Should fail verification because |board| arg is bad."""
     74         self._DARGS['board'] = None
     75         self.assertRaises(error.SuiteArgumentException,
     76                           dynamic_suite.SuiteSpec,
     77                           **self._DARGS)
     78 
     79 
     80     def testVetReimageAndRunNameArgFail(self):
     81         """Should fail verification because |name| arg is bad."""
     82         self._DARGS['name'] = None
     83         self.assertRaises(error.SuiteArgumentException,
     84                           dynamic_suite.SuiteSpec,
     85                           **self._DARGS)
     86 
     87 
     88     def testVetReimageAndRunJobArgFail(self):
     89         """Should fail verification because |job| arg is bad."""
     90         self._DARGS['job'] = None
     91         self.assertRaises(error.SuiteArgumentException,
     92                           dynamic_suite.SuiteSpec,
     93                           **self._DARGS)
     94 
     95 
     96     def testOverrideOptionalReimageAndRunArgs(self):
     97         """Should verify that optional args can be overridden."""
     98         spec = dynamic_suite.SuiteSpec(**self._DARGS)
     99         self.assertEquals(spec.pool, 'pool:' + self._DARGS['pool'])
    100         self.assertEquals(spec.num, self._DARGS['num'])
    101         self.assertEquals(spec.check_hosts, self._DARGS['check_hosts'])
    102         self.assertEquals(spec.add_experimental,
    103                           self._DARGS['add_experimental'])
    104         self.assertEquals(spec.suite_dependencies,
    105                           self._DARGS['suite_dependencies'])
    106 
    107 
    108     def testDefaultOptionalReimageAndRunArgs(self):
    109         """Should verify that optional args get defaults."""
    110         del(self._DARGS['pool'])
    111         del(self._DARGS['check_hosts'])
    112         del(self._DARGS['add_experimental'])
    113         del(self._DARGS['num'])
    114         del(self._DARGS['suite_dependencies'])
    115 
    116         spec = dynamic_suite.SuiteSpec(**self._DARGS)
    117         self.assertEquals(spec.pool, None)
    118         self.assertEquals(spec.num, None)
    119         self.assertEquals(spec.check_hosts, True)
    120         self.assertEquals(spec.add_experimental, True)
    121         self.assertEquals(spec.suite_dependencies, [])
    122 
    123 
    124     def testReimageAndSIGTERM(self):
    125         """Should reimage_and_run that causes a SIGTERM and fails cleanly."""
    126         def suicide(*_):
    127             """Send SIGTERM to current process to exit.
    128 
    129             @param _: Ignored.
    130             """
    131             os.kill(os.getpid(), signal.SIGTERM)
    132 
    133         # Mox doesn't play well with SIGTERM, but it does play well with
    134         # with exceptions, so here we're using an exception to simulate
    135         # execution being interrupted by a signal.
    136         class UnhandledSIGTERM(Exception):
    137             """Exception to be raised when SIGTERM is received."""
    138             pass
    139 
    140         def handler(signal_number, frame):
    141             """Handler for receiving a signal.
    142 
    143             @param signal_number: signal number.
    144             @param frame: stack frame object.
    145             """
    146             raise UnhandledSIGTERM()
    147 
    148         signal.signal(signal.SIGTERM, handler)
    149         spec = self.mox.CreateMock(dynamic_suite.SuiteSpec)
    150         spec.builds = self._BUILDS
    151         spec.test_source_build = Suite.get_test_source_build(self._BUILDS)
    152         spec.devserver = self.mox.CreateMock(dev_server.ImageServer)
    153         spec.devserver.stage_artifacts(
    154                 spec.builds[provision.CROS_VERSION_PREFIX],
    155                 ['control_files', 'test_suites']).WithSideEffects(suicide)
    156         spec.run_prod_code = False
    157 
    158         self.mox.ReplayAll()
    159 
    160         self.assertRaises(UnhandledSIGTERM,
    161                           dynamic_suite._perform_reimage_and_run,
    162                           spec, None, None, None)
    163 
    164 
    165 if __name__ == '__main__':
    166     unittest.main()
    167