xref: /aosp_15_r20/external/autotest/server/cros/dynamic_suite/dynamic_suite_unittest.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
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