xref: /aosp_15_r20/external/autotest/server/hosts/factory_unittest.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li#!/usr/bin/python3
2*9c5db199SXin Li# Copyright 2016 The Chromium OS Authors. All rights reserved.
3*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be
4*9c5db199SXin Li# found in the LICENSE file.
5*9c5db199SXin Li
6*9c5db199SXin Liimport unittest
7*9c5db199SXin Li
8*9c5db199SXin Liimport common
9*9c5db199SXin Lifrom autotest_lib.client.common_lib import error
10*9c5db199SXin Lifrom autotest_lib.server.hosts import base_label_unittest, factory
11*9c5db199SXin Lifrom autotest_lib.server.hosts import host_info
12*9c5db199SXin Li
13*9c5db199SXin Li
14*9c5db199SXin Liclass MockHost(object):
15*9c5db199SXin Li    """Mock host object with no side effects."""
16*9c5db199SXin Li    def __init__(self, hostname, **args):
17*9c5db199SXin Li        self._init_args = args
18*9c5db199SXin Li        self._init_args['hostname'] = hostname
19*9c5db199SXin Li
20*9c5db199SXin Li
21*9c5db199SXin Li    def job_start(self):
22*9c5db199SXin Li        """Only method called by factory."""
23*9c5db199SXin Li        pass
24*9c5db199SXin Li
25*9c5db199SXin Li
26*9c5db199SXin Liclass MockConnectivity(object):
27*9c5db199SXin Li    """Mock connectivity object with no side effects."""
28*9c5db199SXin Li    def __init__(self, hostname, **args):
29*9c5db199SXin Li        pass
30*9c5db199SXin Li
31*9c5db199SXin Li    def run(self, *args, **kwargs):
32*9c5db199SXin Li        pass
33*9c5db199SXin Li
34*9c5db199SXin Li    def close(self):
35*9c5db199SXin Li        pass
36*9c5db199SXin Li
37*9c5db199SXin Li
38*9c5db199SXin Lidef _gen_mock_host(name, check_host=False):
39*9c5db199SXin Li    """Create an identifiable mock host closs.
40*9c5db199SXin Li    """
41*9c5db199SXin Li    return type('mock_host_%s' % name, (MockHost,), {
42*9c5db199SXin Li        '_host_cls_name': name,
43*9c5db199SXin Li        'check_host': staticmethod(lambda host, timeout=None: check_host)
44*9c5db199SXin Li    })
45*9c5db199SXin Li
46*9c5db199SXin Li
47*9c5db199SXin Lidef _gen_mock_conn(name):
48*9c5db199SXin Li    """Create an identifiable mock connectivity class.
49*9c5db199SXin Li    """
50*9c5db199SXin Li    return type('mock_conn_%s' % name, (MockConnectivity,),
51*9c5db199SXin Li                {'_conn_cls_name': name})
52*9c5db199SXin Li
53*9c5db199SXin Li
54*9c5db199SXin Lidef _gen_machine_dict(hostname='localhost', labels=[], attributes={}):
55*9c5db199SXin Li    """Generate a machine dictionary with the specified parameters.
56*9c5db199SXin Li
57*9c5db199SXin Li    @param hostname: hostname of machine
58*9c5db199SXin Li    @param labels: list of host labels
59*9c5db199SXin Li    @param attributes: dict of host attributes
60*9c5db199SXin Li
61*9c5db199SXin Li    @return: machine dict with mocked AFE Host object and fake AfeStore.
62*9c5db199SXin Li    """
63*9c5db199SXin Li    afe_host = base_label_unittest.MockAFEHost(labels, attributes)
64*9c5db199SXin Li    store = host_info.InMemoryHostInfoStore()
65*9c5db199SXin Li    store.commit(host_info.HostInfo(labels, attributes))
66*9c5db199SXin Li    return {'hostname': hostname,
67*9c5db199SXin Li            'afe_host': afe_host,
68*9c5db199SXin Li            'host_info_store': store}
69*9c5db199SXin Li
70*9c5db199SXin Li
71*9c5db199SXin Liclass CreateHostUnittests(unittest.TestCase):
72*9c5db199SXin Li    """Tests for create_host function."""
73*9c5db199SXin Li
74*9c5db199SXin Li    def setUp(self):
75*9c5db199SXin Li        """Prevent use of real Host and connectivity objects due to potential
76*9c5db199SXin Li        side effects.
77*9c5db199SXin Li        """
78*9c5db199SXin Li        self._orig_types = factory.host_types
79*9c5db199SXin Li        self._orig_dict = factory.OS_HOST_DICT
80*9c5db199SXin Li        self._orig_cros_host = factory.cros_host.CrosHost
81*9c5db199SXin Li        self._orig_local_host = factory.local_host.LocalHost
82*9c5db199SXin Li        self._orig_ssh_host = factory.ssh_host.SSHHost
83*9c5db199SXin Li
84*9c5db199SXin Li        self.host_types = factory.host_types = []
85*9c5db199SXin Li        self.os_host_dict = factory.OS_HOST_DICT = {}
86*9c5db199SXin Li        factory.cros_host.CrosHost = _gen_mock_host('cros_host')
87*9c5db199SXin Li        factory.local_host.LocalHost = _gen_mock_conn('local')
88*9c5db199SXin Li        factory.ssh_host.SSHHost = _gen_mock_conn('ssh')
89*9c5db199SXin Li
90*9c5db199SXin Li
91*9c5db199SXin Li    def tearDown(self):
92*9c5db199SXin Li        """Clean up mocks."""
93*9c5db199SXin Li        factory.host_types = self._orig_types
94*9c5db199SXin Li        factory.OS_HOST_DICT = self._orig_dict
95*9c5db199SXin Li        factory.cros_host.CrosHost = self._orig_cros_host
96*9c5db199SXin Li        factory.local_host.LocalHost = self._orig_local_host
97*9c5db199SXin Li        factory.ssh_host.SSHHost = self._orig_ssh_host
98*9c5db199SXin Li
99*9c5db199SXin Li
100*9c5db199SXin Li    def test_use_specified(self):
101*9c5db199SXin Li        """Confirm that the specified host class is used."""
102*9c5db199SXin Li        machine = _gen_machine_dict()
103*9c5db199SXin Li        host_obj = factory.create_host(
104*9c5db199SXin Li                machine,
105*9c5db199SXin Li                _gen_mock_host('specified'),
106*9c5db199SXin Li        )
107*9c5db199SXin Li        self.assertEqual(host_obj._host_cls_name, 'specified')
108*9c5db199SXin Li
109*9c5db199SXin Li
110*9c5db199SXin Li    def test_detect_host_by_os_label(self):
111*9c5db199SXin Li        """Confirm that the host object is selected by the os label.
112*9c5db199SXin Li        """
113*9c5db199SXin Li        machine = _gen_machine_dict(labels=['os:foo'])
114*9c5db199SXin Li        self.os_host_dict['foo'] = _gen_mock_host('foo')
115*9c5db199SXin Li        host_obj = factory.create_host(machine)
116*9c5db199SXin Li        self.assertEqual(host_obj._host_cls_name, 'foo')
117*9c5db199SXin Li
118*9c5db199SXin Li
119*9c5db199SXin Li    def test_detect_host_by_os_type_attribute(self):
120*9c5db199SXin Li        """Confirm that the host object is selected by the os_type attribute
121*9c5db199SXin Li        and that the os_type attribute is preferred over the os label.
122*9c5db199SXin Li        """
123*9c5db199SXin Li        machine = _gen_machine_dict(labels=['os:foo'],
124*9c5db199SXin Li                                         attributes={'os_type': 'bar'})
125*9c5db199SXin Li        self.os_host_dict['foo'] = _gen_mock_host('foo')
126*9c5db199SXin Li        self.os_host_dict['bar'] = _gen_mock_host('bar')
127*9c5db199SXin Li        host_obj = factory.create_host(machine)
128*9c5db199SXin Li        self.assertEqual(host_obj._host_cls_name, 'bar')
129*9c5db199SXin Li
130*9c5db199SXin Li
131*9c5db199SXin Li    def test_detect_host_by_check_host(self):
132*9c5db199SXin Li        """Confirm check_host logic chooses a host object when label/attribute
133*9c5db199SXin Li        detection fails.
134*9c5db199SXin Li        """
135*9c5db199SXin Li        machine = _gen_machine_dict()
136*9c5db199SXin Li        self.host_types.append(_gen_mock_host('first', check_host=False))
137*9c5db199SXin Li        self.host_types.append(_gen_mock_host('second', check_host=True))
138*9c5db199SXin Li        self.host_types.append(_gen_mock_host('third', check_host=False))
139*9c5db199SXin Li        host_obj = factory.create_host(machine)
140*9c5db199SXin Li        self.assertEqual(host_obj._host_cls_name, 'second')
141*9c5db199SXin Li
142*9c5db199SXin Li
143*9c5db199SXin Li    def test_detect_host_fallback_to_cros_host(self):
144*9c5db199SXin Li        """Confirm fallback to CrosHost when all other detection fails.
145*9c5db199SXin Li        """
146*9c5db199SXin Li        machine = _gen_machine_dict()
147*9c5db199SXin Li        host_obj = factory.create_host(machine)
148*9c5db199SXin Li        self.assertEqual(host_obj._host_cls_name, 'cros_host')
149*9c5db199SXin Li
150*9c5db199SXin Li
151*9c5db199SXin Li    def test_choose_connectivity_local(self):
152*9c5db199SXin Li        """Confirm local connectivity class used when hostname is localhost.
153*9c5db199SXin Li        """
154*9c5db199SXin Li        machine = _gen_machine_dict(hostname='localhost')
155*9c5db199SXin Li        host_obj = factory.create_host(machine)
156*9c5db199SXin Li        self.assertEqual(host_obj._conn_cls_name, 'local')
157*9c5db199SXin Li
158*9c5db199SXin Li
159*9c5db199SXin Li    def test_choose_connectivity_ssh(self):
160*9c5db199SXin Li        """Confirm ssh connectivity class used when configured and hostname
161*9c5db199SXin Li        is not localhost.
162*9c5db199SXin Li        """
163*9c5db199SXin Li        machine = _gen_machine_dict(hostname='somehost')
164*9c5db199SXin Li        host_obj = factory.create_host(machine)
165*9c5db199SXin Li        self.assertEqual(host_obj._conn_cls_name, 'ssh')
166*9c5db199SXin Li
167*9c5db199SXin Li
168*9c5db199SXin Li    def test_argument_passthrough(self):
169*9c5db199SXin Li        """Confirm that detected and specified arguments are passed through to
170*9c5db199SXin Li        the host object.
171*9c5db199SXin Li        """
172*9c5db199SXin Li        machine = _gen_machine_dict(hostname='localhost')
173*9c5db199SXin Li        host_obj = factory.create_host(machine, foo='bar')
174*9c5db199SXin Li        self.assertEqual(host_obj._init_args['hostname'], 'localhost')
175*9c5db199SXin Li        self.assertTrue('afe_host' in host_obj._init_args)
176*9c5db199SXin Li        self.assertTrue('host_info_store' in host_obj._init_args)
177*9c5db199SXin Li        self.assertEqual(host_obj._init_args['foo'], 'bar')
178*9c5db199SXin Li
179*9c5db199SXin Li
180*9c5db199SXin Li    def test_global_ssh_params(self):
181*9c5db199SXin Li        """Confirm passing of ssh parameters set as globals.
182*9c5db199SXin Li        """
183*9c5db199SXin Li        factory.ssh_user = 'foo'
184*9c5db199SXin Li        factory.ssh_pass = 'bar'
185*9c5db199SXin Li        factory.ssh_port = 1
186*9c5db199SXin Li        factory.ssh_verbosity_flag = 'baz'
187*9c5db199SXin Li        factory.ssh_options = 'zip'
188*9c5db199SXin Li        machine = _gen_machine_dict()
189*9c5db199SXin Li        try:
190*9c5db199SXin Li            host_obj = factory.create_host(machine)
191*9c5db199SXin Li            self.assertEqual(host_obj._init_args['user'], 'foo')
192*9c5db199SXin Li            self.assertEqual(host_obj._init_args['password'], 'bar')
193*9c5db199SXin Li            self.assertEqual(host_obj._init_args['port'], 1)
194*9c5db199SXin Li            self.assertEqual(host_obj._init_args['ssh_verbosity_flag'], 'baz')
195*9c5db199SXin Li            self.assertEqual(host_obj._init_args['ssh_options'], 'zip')
196*9c5db199SXin Li        finally:
197*9c5db199SXin Li            del factory.ssh_user
198*9c5db199SXin Li            del factory.ssh_pass
199*9c5db199SXin Li            del factory.ssh_port
200*9c5db199SXin Li            del factory.ssh_verbosity_flag
201*9c5db199SXin Li            del factory.ssh_options
202*9c5db199SXin Li
203*9c5db199SXin Li
204*9c5db199SXin Li    def test_host_attribute_ssh_params(self):
205*9c5db199SXin Li        """Confirm passing of ssh parameters from host attributes.
206*9c5db199SXin Li        """
207*9c5db199SXin Li        machine = _gen_machine_dict(attributes={'ssh_user': 'somebody',
208*9c5db199SXin Li                                                'ssh_port': 100,
209*9c5db199SXin Li                                                'ssh_verbosity_flag': 'verb',
210*9c5db199SXin Li                                                'ssh_options': 'options'})
211*9c5db199SXin Li        host_obj = factory.create_host(machine)
212*9c5db199SXin Li        self.assertEqual(host_obj._init_args['user'], 'somebody')
213*9c5db199SXin Li        self.assertEqual(host_obj._init_args['port'], 100)
214*9c5db199SXin Li        self.assertEqual(host_obj._init_args['ssh_verbosity_flag'], 'verb')
215*9c5db199SXin Li        self.assertEqual(host_obj._init_args['ssh_options'], 'options')
216*9c5db199SXin Li
217*9c5db199SXin Li
218*9c5db199SXin Liif __name__ == '__main__':
219*9c5db199SXin Li    unittest.main()
220*9c5db199SXin Li
221