xref: /aosp_15_r20/external/autotest/server/cros/provisioner_unittest.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1#!/usr/bin/python3
2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import unittest
7from unittest import mock
8
9import common
10from autotest_lib.client.common_lib.cros import kernel_utils
11from autotest_lib.server.cros import provisioner
12
13
14class _StubUpdateError(provisioner._AttributedUpdateError):
15    STUB_MESSAGE = 'Stub message'
16    STUB_PATTERN = 'Stub pattern matched'
17    _SUMMARY = 'Stub summary'
18    _CLASSIFIERS = [
19            (STUB_MESSAGE, STUB_MESSAGE),
20            ('Stub .*', STUB_PATTERN),
21    ]
22
23    def __init__(self, info, msg):
24        super(_StubUpdateError, self).__init__('Stub %s' % info, msg)
25
26
27class TestErrorClassifications(unittest.TestCase):
28    """Test error message handling in `_AttributedUpdateError`."""
29
30    def test_exception_message(self):
31        """Test that the exception string includes its arguments."""
32        info = 'info marker'
33        msg = 'an error message'
34        stub = _StubUpdateError(info, msg)
35        self.assertIn(info, str(stub))
36        self.assertIn(msg, str(stub))
37
38    def test_classifier_message(self):
39        """Test that the exception classifier can match a simple string."""
40        info = 'info marker'
41        stub = _StubUpdateError(info, _StubUpdateError.STUB_MESSAGE)
42        self.assertNotIn(info, stub.failure_summary)
43        self.assertIn(_StubUpdateError._SUMMARY, stub.failure_summary)
44        self.assertIn(_StubUpdateError.STUB_MESSAGE, stub.failure_summary)
45
46    def test_classifier_pattern(self):
47        """Test that the exception classifier can match a regex."""
48        info = 'info marker'
49        stub = _StubUpdateError(info, 'Stub this is a test')
50        self.assertNotIn(info, stub.failure_summary)
51        self.assertIn(_StubUpdateError._SUMMARY, stub.failure_summary)
52        self.assertIn(_StubUpdateError.STUB_PATTERN, stub.failure_summary)
53
54    def test_classifier_unmatched(self):
55        """Test exception summary when no classifier matches."""
56        info = 'info marker'
57        stub = _StubUpdateError(info, 'This matches no pattern')
58        self.assertNotIn(info, stub.failure_summary)
59        self.assertIn(_StubUpdateError._SUMMARY, stub.failure_summary)
60
61    def test_host_update_error(self):
62        """Test the `HostUpdateError` classifier."""
63        exception = provisioner.HostUpdateError('chromeos6-row3-rack3-host19',
64                                                'Fake message')
65        self.assertTrue(isinstance(exception.failure_summary, str))
66
67    def test_image_install_error(self):
68        """Test the `ImageInstallError` classifier."""
69        exception = provisioner.ImageInstallError(
70                'chromeos6-row3-rack3-host19', 'chromeos4-devserver7.cros',
71                'Fake message')
72        self.assertTrue(isinstance(exception.failure_summary, str))
73
74    def test_new_build_update_error(self):
75        """Test the `NewBuildUpdateError` classifier."""
76        exception = provisioner.NewBuildUpdateError('R68-10621.0.0',
77                                                    'Fake message')
78        self.assertTrue(isinstance(exception.failure_summary, str))
79
80
81class TestProvisioner(unittest.TestCase):
82    """Test provisioner module."""
83
84    def testParseBuildFromUpdateUrlwithUpdate(self):
85        """Test that we properly parse the build from an update_url."""
86        update_url = ('http://172.22.50.205:8082/update/lumpy-release/'
87                      'R27-3837.0.0')
88        expected_value = 'lumpy-release/R27-3837.0.0'
89        self.assertEqual(provisioner.url_to_image_name(update_url),
90                         expected_value)
91
92    def testGetRemoteScript(self):
93        """Test _get_remote_script() behaviors."""
94        update_url = ('http://172.22.50.205:8082/update/lumpy-chrome-perf/'
95                      'R28-4444.0.0-b2996')
96        script_name = 'fubar'
97        local_script = '/usr/local/bin/%s' % script_name
98
99        host = mock.MagicMock()
100        cros_provisioner = provisioner.ChromiumOSProvisioner(update_url,
101                                                             host=host)
102        host.path_exists.return_value = True
103
104        # Simple case:  file exists on DUT
105        self.assertEqual(cros_provisioner._get_remote_script(script_name),
106                         local_script)
107        host.path_exists.assert_called_with(local_script)
108
109        fake_shell = '/bin/ash'
110        tmp_script = '/usr/local/tmp/%s' % script_name
111        fake_res = fake_result('#!%s\n' % fake_shell)
112
113        host.path_exists.return_value = False
114        host.run.return_value = fake_res
115
116        # Complicated case:  script not on DUT, so try to download it.
117        self.assertEqual(cros_provisioner._get_remote_script(script_name),
118                         '%s %s' % (fake_shell, tmp_script))
119        host.path_exists.assert_called_with(local_script)
120
121
122class fake_result(object):
123    """A fake result with stdout attribute."""
124    def __init__(self, result):
125        self.stdout = result
126
127
128class TestProvisioner2(unittest.TestCase):
129    """Another test for provisioner module that using mock."""
130
131    def testAlwaysRunQuickProvision(self):
132        """Tests that we call quick provsion for all kinds of builds."""
133        image = 'foo-whatever/R65-1234.5.6'
134        devserver = 'http://mock_devserver'
135        provisioner.dev_server = mock.MagicMock()
136        provisioner.metrics = mock.MagicMock()
137        host = mock.MagicMock()
138        update_url = '%s/update/%s' % (devserver, image)
139        cros_provisioner = provisioner.ChromiumOSProvisioner(update_url, host)
140        cros_provisioner.check_update_status = mock.MagicMock()
141        kernel_utils.verify_kernel_state_after_update = mock.MagicMock()
142        kernel_utils.verify_kernel_state_after_update.return_value = 3
143        kernel_utils.verify_boot_expectations = mock.MagicMock()
144
145        cros_provisioner.run_provision()
146        host.run.assert_any_call(
147                '/usr/local/bin/quick-provision --noreboot %s '
148                '%s/download/chromeos-image-archive' % (image, devserver))
149
150
151if __name__ == '__main__':
152    unittest.main()
153