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