1#!/usr/bin/python3 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 12from unittest import mock 13from unittest.mock import MagicMock 14 15import common 16from autotest_lib.client.common_lib import base_job, error 17from autotest_lib.server.cros import provision 18from autotest_lib.server.cros.dynamic_suite import dynamic_suite 19from autotest_lib.server.cros.dynamic_suite.suite import Suite 20 21 22class DynamicSuiteTest(unittest.TestCase): 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 = { 36 'name': 'name', 37 'builds': self._BUILDS, 38 'board': 'board', 39 'job': MagicMock(base_job.base_job), 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 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.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['suite_dependencies']) 108 109 spec = dynamic_suite._SuiteSpec(**self._DARGS) 110 self.assertEquals(spec.pool, None) 111 self.assertEquals(spec.check_hosts, True) 112 self.assertEquals(spec.add_experimental, True) 113 self.assertEquals( 114 spec.suite_dependencies, 115 ['cros-version:build_1', 'fwrw-version:fwrw_build_1']) 116 117 118 def testReimageAndSIGTERM(self): 119 """Should reimage_and_run that causes a SIGTERM and fails cleanly.""" 120 def suicide(*_, **__): 121 """Send SIGTERM to current process to exit. 122 123 @param _: Ignored. 124 @param __: Ignored. 125 """ 126 os.kill(os.getpid(), signal.SIGTERM) 127 128 # Mox doesn't play well with SIGTERM, but it does play well with 129 # with exceptions, so here we're using an exception to simulate 130 # execution being interrupted by a signal. 131 class UnhandledSIGTERM(Exception): 132 """Exception to be raised when SIGTERM is received.""" 133 pass 134 135 def handler(signal_number, frame): 136 """Handler for receiving a signal. 137 138 @param signal_number: signal number. 139 @param frame: stack frame object. 140 """ 141 raise UnhandledSIGTERM() 142 143 signal.signal(signal.SIGTERM, handler) 144 spec = mock.MagicMock() 145 spec.builds = self._BUILDS 146 spec.test_source_build = Suite.get_test_source_build(self._BUILDS) 147 spec.devserver.stage_artifacts.side_effect = suicide 148 spec.run_prod_code = False 149 150 self.assertRaises(UnhandledSIGTERM, 151 dynamic_suite._perform_reimage_and_run, 152 spec, None, None, None) 153 154 155if __name__ == '__main__': 156 unittest.main() 157