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