xref: /aosp_15_r20/external/autotest/server/hosts/cros_host_unittest.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li#!/usr/bin/python3
2*9c5db199SXin Li# pylint: disable=missing-docstring
3*9c5db199SXin Li
4*9c5db199SXin Liimport unittest
5*9c5db199SXin Lifrom unittest import mock
6*9c5db199SXin Li
7*9c5db199SXin Liimport common
8*9c5db199SXin Li
9*9c5db199SXin Lifrom autotest_lib.client.common_lib import error
10*9c5db199SXin Lifrom autotest_lib.server.cros.servo import servo
11*9c5db199SXin Lifrom autotest_lib.server.hosts import cros_host
12*9c5db199SXin Lifrom autotest_lib.server.hosts import servo_constants
13*9c5db199SXin Lifrom autotest_lib.server.hosts import host_info
14*9c5db199SXin Li
15*9c5db199SXin LiCROSSYSTEM_RESULT = '''
16*9c5db199SXin Lifwb_tries              = 0                              # Fake comment
17*9c5db199SXin Lifw_vboot2              = 1                              # Fake comment
18*9c5db199SXin Lifwid                   = Google_Reef.9933.0.0           # Fake comment
19*9c5db199SXin Lifwupdate_tries         = 0                              #
20*9c5db199SXin Lifw_tried               = B                              #
21*9c5db199SXin Lifw_try_count           = 0                              #
22*9c5db199SXin Li'''
23*9c5db199SXin Li
24*9c5db199SXin LiNON_UNI_LSB_RELEASE_OUTPUT = '''
25*9c5db199SXin LiCHROMEOS_RELEASE_BOARD=reef
26*9c5db199SXin Li'''
27*9c5db199SXin Li
28*9c5db199SXin LiUNI_LSB_RELEASE_OUTPUT = '''
29*9c5db199SXin LiCHROMEOS_RELEASE_BOARD=coral
30*9c5db199SXin LiCHROMEOS_RELEASE_UNIBUILD=1
31*9c5db199SXin Li'''
32*9c5db199SXin Li
33*9c5db199SXin LiSERVO_STATE_PREFIX = servo_constants.SERVO_STATE_LABEL_PREFIX
34*9c5db199SXin Li
35*9c5db199SXin Li
36*9c5db199SXin Liclass MockCmd(object):
37*9c5db199SXin Li    """Simple mock command with base command and results"""
38*9c5db199SXin Li
39*9c5db199SXin Li    def __init__(self, cmd, exit_status, stdout):
40*9c5db199SXin Li        self.cmd = cmd
41*9c5db199SXin Li        self.stdout = stdout
42*9c5db199SXin Li        self.exit_status = exit_status
43*9c5db199SXin Li
44*9c5db199SXin Li
45*9c5db199SXin Liclass MockHost(cros_host.CrosHost):
46*9c5db199SXin Li    """Simple host for running mock'd host commands"""
47*9c5db199SXin Li
48*9c5db199SXin Li    def __init__(self, *args):
49*9c5db199SXin Li        self._mock_cmds = {c.cmd: c for c in args}
50*9c5db199SXin Li        self.hostname = 'MockHost'
51*9c5db199SXin Li
52*9c5db199SXin Li    def run(self, command, **kwargs):
53*9c5db199SXin Li        """Finds the matching result by command value"""
54*9c5db199SXin Li        mock_cmd = self._mock_cmds[command]
55*9c5db199SXin Li        file_out = kwargs.get('stdout_tee', None)
56*9c5db199SXin Li        if file_out:
57*9c5db199SXin Li            file_out.write(mock_cmd.stdout)
58*9c5db199SXin Li        return mock_cmd
59*9c5db199SXin Li
60*9c5db199SXin Li
61*9c5db199SXin Liclass GetPlatformModelTests(unittest.TestCase):
62*9c5db199SXin Li    """Unit tests for CrosHost.get_platform_model"""
63*9c5db199SXin Li
64*9c5db199SXin Li    def test_cros_config_succeeds(self):
65*9c5db199SXin Li        host = MockHost(
66*9c5db199SXin Li                MockCmd('cat /etc/lsb-release', 0, UNI_LSB_RELEASE_OUTPUT),
67*9c5db199SXin Li                MockCmd('cros_config / name', 0, 'coral'))
68*9c5db199SXin Li        self.assertEqual(host.get_platform(), 'coral')
69*9c5db199SXin Li
70*9c5db199SXin Li    def test_cros_config_resorts_to_fallback(self):
71*9c5db199SXin Li        host = MockHost(
72*9c5db199SXin Li                MockCmd('cat /etc/lsb-release', 0, UNI_LSB_RELEASE_OUTPUT),
73*9c5db199SXin Li                MockCmd('cros_config / name', 1, ''),
74*9c5db199SXin Li                MockCmd('mosys platform model', 0, 'coral'))
75*9c5db199SXin Li        self.assertEqual(host.get_platform(), 'coral')
76*9c5db199SXin Li
77*9c5db199SXin Li    def test_cros_config_fails(self):
78*9c5db199SXin Li        host = MockHost(
79*9c5db199SXin Li                MockCmd('cat /etc/lsb-release', 0, UNI_LSB_RELEASE_OUTPUT),
80*9c5db199SXin Li                MockCmd('cros_config / name', 1, ''),
81*9c5db199SXin Li                MockCmd('mosys platform model', 1, ''),
82*9c5db199SXin Li                MockCmd('crossystem', 0, CROSSYSTEM_RESULT))
83*9c5db199SXin Li        self.assertEqual(host.get_platform(), 'reef')
84*9c5db199SXin Li
85*9c5db199SXin Li    def test_non_unibuild(self):
86*9c5db199SXin Li        host = MockHost(
87*9c5db199SXin Li                MockCmd('cat /etc/lsb-release', 0, NON_UNI_LSB_RELEASE_OUTPUT),
88*9c5db199SXin Li                MockCmd('crossystem', 0, CROSSYSTEM_RESULT))
89*9c5db199SXin Li        self.assertEqual(host.get_platform(), 'reef')
90*9c5db199SXin Li
91*9c5db199SXin Li    def test_cat_lsb_fails(self):
92*9c5db199SXin Li        host = MockHost(
93*9c5db199SXin Li                MockCmd('cat /etc/lsb-release', 1, ''),
94*9c5db199SXin Li                MockCmd('crossystem', 0, CROSSYSTEM_RESULT))
95*9c5db199SXin Li        self.assertEqual(host.get_platform(), 'reef')
96*9c5db199SXin Li
97*9c5db199SXin Li
98*9c5db199SXin Liclass DictFilteringTestCase(unittest.TestCase):
99*9c5db199SXin Li    """Tests for dict filtering methods on CrosHost."""
100*9c5db199SXin Li
101*9c5db199SXin Li    def test_get_chameleon_arguments(self):
102*9c5db199SXin Li        got = cros_host.CrosHost.get_chameleon_arguments({
103*9c5db199SXin Li            'chameleon_host': 'host',
104*9c5db199SXin Li            'spam': 'eggs',
105*9c5db199SXin Li        })
106*9c5db199SXin Li        self.assertEqual(got, {'chameleon_host': 'host'})
107*9c5db199SXin Li
108*9c5db199SXin Li    def test_get_pdtester_arguments(self):
109*9c5db199SXin Li        got = cros_host.CrosHost.get_pdtester_arguments({
110*9c5db199SXin Li            'pdtester_host': 'host',
111*9c5db199SXin Li            'spam': 'eggs',
112*9c5db199SXin Li        })
113*9c5db199SXin Li        self.assertEqual(got, {'pdtester_host': 'host'})
114*9c5db199SXin Li
115*9c5db199SXin Li    def test_get_servo_arguments(self):
116*9c5db199SXin Li        got = cros_host.CrosHost.get_servo_arguments({
117*9c5db199SXin Li            servo_constants.SERVO_HOST_ATTR: 'host',
118*9c5db199SXin Li            'spam': 'eggs',
119*9c5db199SXin Li        })
120*9c5db199SXin Li        self.assertEqual(got, {servo_constants.SERVO_HOST_ATTR: 'host'})
121*9c5db199SXin Li
122*9c5db199SXin Li
123*9c5db199SXin Liclass DictFilteringTestCase(unittest.TestCase):
124*9c5db199SXin Li    """Test to verify servo_state was set-up as label in host_info_store"""
125*9c5db199SXin Li
126*9c5db199SXin Li    def create_host(self):
127*9c5db199SXin Li        host = MockHost()
128*9c5db199SXin Li        host.servo = None
129*9c5db199SXin Li        host._servo_host = mock.Mock()
130*9c5db199SXin Li        servo = mock.Mock()
131*9c5db199SXin Li        servo.get_servo_type.return_value = None
132*9c5db199SXin Li        host._servo_host.get_servo.return_value = servo
133*9c5db199SXin Li        host._servo_host.get_servo_state.return_value = 'SOME_STATE'
134*9c5db199SXin Li        host.host_info_store = host_info.InMemoryHostInfoStore()
135*9c5db199SXin Li        return host
136*9c5db199SXin Li
137*9c5db199SXin Li    def test_do_not_update_label_when_servo_host_is_not_inited(self):
138*9c5db199SXin Li        host = self.create_host()
139*9c5db199SXin Li        host._servo_host = None
140*9c5db199SXin Li
141*9c5db199SXin Li        host.set_servo_state('some_status')
142*9c5db199SXin Li        self.assertEqual(host.host_info_store.get().get_label_value(SERVO_STATE_PREFIX), 'some_status')
143*9c5db199SXin Li
144*9c5db199SXin Li    def test_do_not_update_label_when_servo_state_is_None(self):
145*9c5db199SXin Li        host = self.create_host()
146*9c5db199SXin Li
147*9c5db199SXin Li        host.set_servo_state(None)
148*9c5db199SXin Li        host._servo_host.get_servo_state.assert_not_called()
149*9c5db199SXin Li        self.assertEqual(host.host_info_store.get().get_label_value(SERVO_STATE_PREFIX), '')
150*9c5db199SXin Li
151*9c5db199SXin Li    def test_repair_servo_set_servo_state_after_repair_when_repair_is_fail(self):
152*9c5db199SXin Li        host = self.create_host()
153*9c5db199SXin Li        host._servo_host.repair.side_effect = Exception('Something bad')
154*9c5db199SXin Li
155*9c5db199SXin Li        try:
156*9c5db199SXin Li            host.repair_servo()
157*9c5db199SXin Li            self.assertEqual("Exception is", 'expecting to raise')
158*9c5db199SXin Li        except:
159*9c5db199SXin Li            pass
160*9c5db199SXin Li        host._servo_host.get_servo_state.assert_called()
161*9c5db199SXin Li        self.assertEqual(host.host_info_store.get().get_label_value(SERVO_STATE_PREFIX), 'SOME_STATE')
162*9c5db199SXin Li
163*9c5db199SXin Li    def test_repair_servo_set_servo_state_after_repair_when_repair_is_not_fail(self):
164*9c5db199SXin Li        host = self.create_host()
165*9c5db199SXin Li        try:
166*9c5db199SXin Li            host.repair_servo()
167*9c5db199SXin Li        except:
168*9c5db199SXin Li            self.assertEqual("Exception is not", 'expected')
169*9c5db199SXin Li            pass
170*9c5db199SXin Li        host._servo_host.get_servo_state.assert_called()
171*9c5db199SXin Li        self.assertEqual(host.host_info_store.get().get_label_value(SERVO_STATE_PREFIX), 'SOME_STATE')
172*9c5db199SXin Li
173*9c5db199SXin Li    def test_set_servo_host_update_servo_state_when_host_exist(self):
174*9c5db199SXin Li        host = self.create_host()
175*9c5db199SXin Li        host._servo_host = mock.Mock()
176*9c5db199SXin Li        servo = mock.Mock()
177*9c5db199SXin Li        servo.get_servo_type.return_value = None
178*9c5db199SXin Li        host._servo_host.get_servo.return_value = servo
179*9c5db199SXin Li        host._servo_host.get_servo_state.return_value = 'SOME_STATE'
180*9c5db199SXin Li        self.assertEqual(host.host_info_store.get().get_label_value(SERVO_STATE_PREFIX), '')
181*9c5db199SXin Li
182*9c5db199SXin Li        try:
183*9c5db199SXin Li            host.repair_servo()
184*9c5db199SXin Li        except:
185*9c5db199SXin Li            self.assertEqual("Exception is not", 'expected')
186*9c5db199SXin Li            pass
187*9c5db199SXin Li        host._servo_host.get_servo_state.assert_called()
188*9c5db199SXin Li        self.assertEqual(host.host_info_store.get().get_label_value(SERVO_STATE_PREFIX), 'SOME_STATE')
189*9c5db199SXin Li
190*9c5db199SXin Li    def test_set_servo_host_use_passed_servo_state_when_host_is_None(self):
191*9c5db199SXin Li        host = self.create_host()
192*9c5db199SXin Li
193*9c5db199SXin Li        host.set_servo_host(None, 'passed_State')
194*9c5db199SXin Li        self.assertEqual(host.host_info_store.get().get_label_value(SERVO_STATE_PREFIX), 'passed_State')
195*9c5db199SXin Li
196*9c5db199SXin Li    def test_set_servo_host_use_servo_state_from_host_when_host_is_passed(self):
197*9c5db199SXin Li        host = self.create_host()
198*9c5db199SXin Li        servo_host = mock.Mock()
199*9c5db199SXin Li        servo = mock.Mock()
200*9c5db199SXin Li        servo.get_servo_type.return_value = None
201*9c5db199SXin Li        servo_host.get_servo.return_value = servo
202*9c5db199SXin Li        servo_host.get_servo_state.return_value = 'state_of_host'
203*9c5db199SXin Li
204*9c5db199SXin Li        host.set_servo_host(servo_host)
205*9c5db199SXin Li        self.assertEqual(host.host_info_store.get().get_label_value(SERVO_STATE_PREFIX), 'state_of_host')
206*9c5db199SXin Li
207*9c5db199SXin Li        servo_host.get_servo_state.return_value = 'state_of_host2'
208*9c5db199SXin Li        host.set_servo_host(servo_host, 'passed_State')
209*9c5db199SXin Li        self.assertEqual(host.host_info_store.get().get_label_value(SERVO_STATE_PREFIX), 'state_of_host2')
210*9c5db199SXin Li
211*9c5db199SXin Liclass CrosHostTestCase(unittest.TestCase):
212*9c5db199SXin Li    """Tests to verify CrosHost."""
213*9c5db199SXin Li
214*9c5db199SXin Li    class TestCrosHost(cros_host.CrosHost):
215*9c5db199SXin Li        def __init__(self, *args, **kwargs):
216*9c5db199SXin Li            self.hostname = 'hostname'
217*9c5db199SXin Li            self.servo = mock.create_autospec(servo.Servo)
218*9c5db199SXin Li
219*9c5db199SXin Li    @mock.patch('autotest_lib.server.hosts.cros_host.dev_server')
220*9c5db199SXin Li    def test_stage_build_to_usb(self, devserver_mock):
221*9c5db199SXin Li        host = self.TestCrosHost()
222*9c5db199SXin Li        image_server = mock.MagicMock()
223*9c5db199SXin Li        devserver_mock.ImageServer.resolve.return_value = image_server
224*9c5db199SXin Li        image_server.get_test_image_url.return_value = 'image_url'
225*9c5db199SXin Li
226*9c5db199SXin Li        host.stage_build_to_usb('board/version')
227*9c5db199SXin Li
228*9c5db199SXin Li        image_server.stage_artifacts.assert_called_with('board/version', ['test_image'])
229*9c5db199SXin Li        host.servo.image_to_servo_usb.assert_called_with('image_url')
230*9c5db199SXin Li
231*9c5db199SXin Li        host.servo.get_power_state_controller.return_value.power_on.assert_called()
232*9c5db199SXin Li
233*9c5db199SXin Li    @mock.patch('autotest_lib.server.hosts.cros_host.dev_server')
234*9c5db199SXin Li    def test_stage_build_to_usb_failure(self, devserver_mock):
235*9c5db199SXin Li        host = self.TestCrosHost()
236*9c5db199SXin Li        image_server = mock.MagicMock()
237*9c5db199SXin Li        devserver_mock.ImageServer.resolve.return_value = image_server
238*9c5db199SXin Li        image_server.get_test_image_url.return_value = 'image_url'
239*9c5db199SXin Li        host.servo.image_to_servo_usb.side_effect = error.AutotestError('download')
240*9c5db199SXin Li
241*9c5db199SXin Li        with self.assertRaises(error.AutotestError):
242*9c5db199SXin Li            host.stage_build_to_usb('board/version')
243*9c5db199SXin Li
244*9c5db199SXin Li        host.servo.get_power_state_controller.return_value.power_on.assert_called()
245*9c5db199SXin Li
246*9c5db199SXin Li
247*9c5db199SXin Liif __name__ == "__main__":
248*9c5db199SXin Li    unittest.main()
249