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 9import mox 10import os 11import signal 12import unittest 13 14from autotest_lib.client.common_lib import base_job, error 15from autotest_lib.client.common_lib.cros import dev_server 16from autotest_lib.server.cros import provision 17from autotest_lib.server.cros.dynamic_suite import dynamic_suite 18from autotest_lib.server.cros.dynamic_suite.suite import Suite 19 20 21class 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 165if __name__ == '__main__': 166 unittest.main() 167