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