| #!/usr/bin/python2 |
| # |
| # Copyright (c) 2016 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Unit tests for frontend/afe/moblab_rpc_interface.py.""" |
| |
| import __builtin__ |
| # The boto module is only available/used in Moblab for validation of cloud |
| # storage access. The module is not available in the test lab environment, |
| # and the import error is handled. |
| import ConfigParser |
| import mox |
| import StringIO |
| import unittest |
| |
| import common |
| |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.common_lib import global_config |
| from autotest_lib.client.common_lib import lsbrelease_utils |
| from autotest_lib.frontend import setup_django_environment |
| from autotest_lib.frontend.afe import frontend_test_utils |
| from autotest_lib.frontend.afe import moblab_rpc_interface |
| from autotest_lib.frontend.afe import rpc_utils |
| from autotest_lib.server import utils |
| from autotest_lib.server.hosts import moblab_host |
| from autotest_lib.client.common_lib import utils as common_lib_utils |
| |
| |
| class MoblabRpcInterfaceTest(mox.MoxTestBase, |
| frontend_test_utils.FrontendTestMixin): |
| """Unit tests for functions in moblab_rpc_interface.py.""" |
| |
| def setUp(self): |
| super(MoblabRpcInterfaceTest, self).setUp() |
| self._frontend_common_setup(fill_data=False) |
| |
| |
| def tearDown(self): |
| self._frontend_common_teardown() |
| |
| |
| def setIsMoblab(self, is_moblab): |
| """Set utils.is_moblab result. |
| |
| @param is_moblab: Value to have utils.is_moblab to return. |
| """ |
| self.mox.StubOutWithMock(utils, 'is_moblab') |
| utils.is_moblab().AndReturn(is_moblab) |
| |
| |
| def _mockReadFile(self, path, lines=[]): |
| """Mock out reading a file line by line. |
| |
| @param path: Path of the file we are mock reading. |
| @param lines: lines of the mock file that will be returned when |
| readLine() is called. |
| """ |
| mockFile = self.mox.CreateMockAnything() |
| for line in lines: |
| mockFile.readline().AndReturn(line) |
| mockFile.readline() |
| mockFile.close() |
| open(path).AndReturn(mockFile) |
| |
| |
| def testMoblabOnlyDecorator(self): |
| """Ensure the moblab only decorator gates functions properly.""" |
| self.setIsMoblab(False) |
| self.mox.ReplayAll() |
| self.assertRaises(error.RPCException, |
| moblab_rpc_interface.get_config_values) |
| |
| |
| def testGetConfigValues(self): |
| """Ensure that the config object is properly converted to a dict.""" |
| self.setIsMoblab(True) |
| config_mock = self.mox.CreateMockAnything() |
| moblab_rpc_interface._CONFIG = config_mock |
| config_mock.get_sections().AndReturn(['section1', 'section2']) |
| config_mock.config = self.mox.CreateMockAnything() |
| config_mock.config.items('section1').AndReturn([('item1', 'value1'), |
| ('item2', 'value2')]) |
| config_mock.config.items('section2').AndReturn([('item3', 'value3'), |
| ('item4', 'value4')]) |
| |
| rpc_utils.prepare_for_serialization( |
| {'section1' : [('item1', 'value1'), |
| ('item2', 'value2')], |
| 'section2' : [('item3', 'value3'), |
| ('item4', 'value4')]}) |
| self.mox.ReplayAll() |
| moblab_rpc_interface.get_config_values() |
| |
| |
| def testUpdateConfig(self): |
| """Ensure that updating the config works as expected.""" |
| self.setIsMoblab(True) |
| moblab_rpc_interface.os = self.mox.CreateMockAnything() |
| |
| self.mox.StubOutWithMock(__builtin__, 'open') |
| self._mockReadFile(global_config.DEFAULT_CONFIG_FILE) |
| |
| self.mox.StubOutWithMock(lsbrelease_utils, 'is_moblab') |
| lsbrelease_utils.is_moblab().AndReturn(True) |
| |
| self._mockReadFile(global_config.DEFAULT_MOBLAB_FILE, |
| ['[section1]', 'item1: value1']) |
| |
| moblab_rpc_interface.os = self.mox.CreateMockAnything() |
| moblab_rpc_interface.os.path = self.mox.CreateMockAnything() |
| moblab_rpc_interface.os.path.exists( |
| moblab_rpc_interface._CONFIG.shadow_file).AndReturn( |
| True) |
| mockShadowFile = self.mox.CreateMockAnything() |
| mockShadowFileContents = StringIO.StringIO() |
| mockShadowFile.__enter__().AndReturn(mockShadowFileContents) |
| mockShadowFile.__exit__(mox.IgnoreArg(), mox.IgnoreArg(), |
| mox.IgnoreArg()) |
| open(moblab_rpc_interface._CONFIG.shadow_file, |
| 'w').AndReturn(mockShadowFile) |
| moblab_rpc_interface.os.system('sudo reboot') |
| |
| self.mox.ReplayAll() |
| moblab_rpc_interface.update_config_handler( |
| {'section1' : [('item1', 'value1'), |
| ('item2', 'value2')], |
| 'section2' : [('item3', 'value3'), |
| ('item4', 'value4')]}) |
| |
| # item1 should not be in the new shadow config as its updated value |
| # matches the original config's value. |
| self.assertEquals( |
| mockShadowFileContents.getvalue(), |
| '[section2]\nitem3 = value3\nitem4 = value4\n\n' |
| '[section1]\nitem2 = value2\n\n') |
| |
| |
| def testResetConfig(self): |
| """Ensure that reset opens the shadow_config file for writing.""" |
| self.setIsMoblab(True) |
| config_mock = self.mox.CreateMockAnything() |
| moblab_rpc_interface._CONFIG = config_mock |
| config_mock.shadow_file = 'shadow_config.ini' |
| self.mox.StubOutWithMock(__builtin__, 'open') |
| mockFile = self.mox.CreateMockAnything() |
| file_contents = self.mox.CreateMockAnything() |
| mockFile.__enter__().AndReturn(file_contents) |
| mockFile.__exit__(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()) |
| open(config_mock.shadow_file, 'w').AndReturn(mockFile) |
| moblab_rpc_interface.os = self.mox.CreateMockAnything() |
| moblab_rpc_interface.os.system('sudo reboot') |
| self.mox.ReplayAll() |
| moblab_rpc_interface.reset_config_settings() |
| |
| |
| def testSetLaunchControlKey(self): |
| """Ensure that the Launch Control key path supplied is copied correctly. |
| """ |
| self.setIsMoblab(True) |
| launch_control_key = '/tmp/launch_control' |
| moblab_rpc_interface.os = self.mox.CreateMockAnything() |
| moblab_rpc_interface.os.path = self.mox.CreateMockAnything() |
| moblab_rpc_interface.os.path.exists(launch_control_key).AndReturn( |
| True) |
| moblab_rpc_interface.shutil = self.mox.CreateMockAnything() |
| moblab_rpc_interface.shutil.copyfile( |
| launch_control_key, |
| moblab_host.MOBLAB_LAUNCH_CONTROL_KEY_LOCATION) |
| moblab_rpc_interface.os.system('sudo restart moblab-devserver-init') |
| self.mox.ReplayAll() |
| moblab_rpc_interface.set_launch_control_key(launch_control_key) |
| |
| |
| def testGetNetworkInfo(self): |
| """Ensure the network info is properly converted to a dict.""" |
| self.setIsMoblab(True) |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface, '_get_network_info') |
| moblab_rpc_interface._get_network_info().AndReturn(('10.0.0.1', True)) |
| self.mox.StubOutWithMock(rpc_utils, 'prepare_for_serialization') |
| |
| rpc_utils.prepare_for_serialization( |
| {'is_connected': True, 'server_ips': ['10.0.0.1']}) |
| self.mox.ReplayAll() |
| moblab_rpc_interface.get_network_info() |
| self.mox.VerifyAll() |
| |
| |
| def testGetNetworkInfoWithNoIp(self): |
| """Queries network info with no public IP address.""" |
| self.setIsMoblab(True) |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface, '_get_network_info') |
| moblab_rpc_interface._get_network_info().AndReturn((None, False)) |
| self.mox.StubOutWithMock(rpc_utils, 'prepare_for_serialization') |
| |
| rpc_utils.prepare_for_serialization( |
| {'is_connected': False}) |
| self.mox.ReplayAll() |
| moblab_rpc_interface.get_network_info() |
| self.mox.VerifyAll() |
| |
| |
| def testGetNetworkInfoWithNoConnectivity(self): |
| """Queries network info with public IP address but no connectivity.""" |
| self.setIsMoblab(True) |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface, '_get_network_info') |
| moblab_rpc_interface._get_network_info().AndReturn(('10.0.0.1', False)) |
| self.mox.StubOutWithMock(rpc_utils, 'prepare_for_serialization') |
| |
| rpc_utils.prepare_for_serialization( |
| {'is_connected': False, 'server_ips': ['10.0.0.1']}) |
| self.mox.ReplayAll() |
| moblab_rpc_interface.get_network_info() |
| self.mox.VerifyAll() |
| |
| |
| def testGetCloudStorageInfo(self): |
| """Ensure the cloud storage info is properly converted to a dict.""" |
| self.setIsMoblab(True) |
| config_mock = self.mox.CreateMockAnything() |
| moblab_rpc_interface._CONFIG = config_mock |
| config_mock.get_config_value( |
| 'CROS', 'image_storage_server').AndReturn('gs://bucket1') |
| config_mock.get_config_value( |
| 'CROS', 'results_storage_server', default=None).AndReturn( |
| 'gs://bucket2') |
| self.mox.StubOutWithMock(moblab_rpc_interface, '_get_boto_config') |
| moblab_rpc_interface._get_boto_config().AndReturn(config_mock) |
| config_mock.sections().AndReturn(['Credentials', 'b']) |
| config_mock.options('Credentials').AndReturn( |
| ['gs_access_key_id', 'gs_secret_access_key']) |
| config_mock.get( |
| 'Credentials', 'gs_access_key_id').AndReturn('key') |
| config_mock.get( |
| 'Credentials', 'gs_secret_access_key').AndReturn('secret') |
| rpc_utils.prepare_for_serialization( |
| { |
| 'gs_access_key_id': 'key', |
| 'gs_secret_access_key' : 'secret', |
| 'use_existing_boto_file': True, |
| 'image_storage_server' : 'gs://bucket1', |
| 'results_storage_server' : 'gs://bucket2' |
| }) |
| self.mox.ReplayAll() |
| moblab_rpc_interface.get_cloud_storage_info() |
| self.mox.VerifyAll() |
| |
| |
| def testValidateCloudStorageInfo(self): |
| """ Ensure the cloud storage info validation flow.""" |
| self.setIsMoblab(True) |
| cloud_storage_info = { |
| 'use_existing_boto_file': False, |
| 'gs_access_key_id': 'key', |
| 'gs_secret_access_key': 'secret', |
| 'image_storage_server': 'gs://bucket1', |
| 'results_storage_server': 'gs://bucket2'} |
| self.mox.StubOutWithMock(moblab_rpc_interface, |
| '_run_bucket_performance_test') |
| moblab_rpc_interface._run_bucket_performance_test( |
| 'key', 'secret', 'gs://bucket1').AndReturn((True, None)) |
| rpc_utils.prepare_for_serialization({'status_ok': True }) |
| self.mox.ReplayAll() |
| moblab_rpc_interface.validate_cloud_storage_info(cloud_storage_info) |
| self.mox.VerifyAll() |
| |
| |
| def testGetBucketNameFromUrl(self): |
| """Gets bucket name from bucket URL.""" |
| self.assertEquals( |
| 'bucket_name-123', |
| moblab_rpc_interface._get_bucket_name_from_url( |
| 'gs://bucket_name-123')) |
| self.assertEquals( |
| 'bucket_name-123', |
| moblab_rpc_interface._get_bucket_name_from_url( |
| 'gs://bucket_name-123/')) |
| self.assertEquals( |
| 'bucket_name-123', |
| moblab_rpc_interface._get_bucket_name_from_url( |
| 'gs://bucket_name-123/a/b/c')) |
| self.assertIsNone(moblab_rpc_interface._get_bucket_name_from_url( |
| 'bucket_name-123/a/b/c')) |
| |
| |
| def testGetShadowConfigFromPartialUpdate(self): |
| """Tests getting shadow configuration based on partial upate.""" |
| partial_config = { |
| 'section1': [ |
| ('opt1', 'value1'), |
| ('opt2', 'value2'), |
| ('opt3', 'value3'), |
| ('opt4', 'value4'), |
| ] |
| } |
| shadow_config_str = "[section1]\nopt2 = value2_1\nopt4 = value4_1" |
| shadow_config = ConfigParser.ConfigParser() |
| shadow_config.readfp(StringIO.StringIO(shadow_config_str)) |
| original_config = self.mox.CreateMockAnything() |
| self.mox.StubOutWithMock(moblab_rpc_interface, '_read_original_config') |
| self.mox.StubOutWithMock(moblab_rpc_interface, '_read_raw_config') |
| moblab_rpc_interface._read_original_config().AndReturn(original_config) |
| moblab_rpc_interface._read_raw_config( |
| moblab_rpc_interface._CONFIG.shadow_file).AndReturn(shadow_config) |
| original_config.get_config_value( |
| 'section1', 'opt1', |
| allow_blank=True, default='').AndReturn('value1') |
| original_config.get_config_value( |
| 'section1', 'opt2', |
| allow_blank=True, default='').AndReturn('value2') |
| original_config.get_config_value( |
| 'section1', 'opt3', |
| allow_blank=True, default='').AndReturn('blah') |
| original_config.get_config_value( |
| 'section1', 'opt4', |
| allow_blank=True, default='').AndReturn('blah') |
| self.mox.ReplayAll() |
| shadow_config = moblab_rpc_interface._get_shadow_config_from_partial_update( |
| partial_config) |
| # opt1 same as the original. |
| self.assertFalse(shadow_config.has_option('section1', 'opt1')) |
| # opt2 reverts back to original |
| self.assertFalse(shadow_config.has_option('section1', 'opt2')) |
| # opt3 is updated from original. |
| self.assertEquals('value3', shadow_config.get('section1', 'opt3')) |
| # opt3 in shadow but updated again. |
| self.assertEquals('value4', shadow_config.get('section1', 'opt4')) |
| self.mox.VerifyAll() |
| |
| |
| def testGetShadowConfigFromPartialUpdateWithNewSection(self): |
| """ |
| Test getting shadown configuration based on partial update with new section. |
| """ |
| partial_config = { |
| 'section2': [ |
| ('opt5', 'value5'), |
| ('opt6', 'value6'), |
| ], |
| } |
| shadow_config_str = "[section1]\nopt2 = value2_1\n" |
| shadow_config = ConfigParser.ConfigParser() |
| shadow_config.readfp(StringIO.StringIO(shadow_config_str)) |
| original_config = self.mox.CreateMockAnything() |
| self.mox.StubOutWithMock(moblab_rpc_interface, '_read_original_config') |
| self.mox.StubOutWithMock(moblab_rpc_interface, '_read_raw_config') |
| moblab_rpc_interface._read_original_config().AndReturn(original_config) |
| moblab_rpc_interface._read_raw_config( |
| moblab_rpc_interface._CONFIG.shadow_file).AndReturn(shadow_config) |
| original_config.get_config_value( |
| 'section2', 'opt5', |
| allow_blank=True, default='').AndReturn('value5') |
| original_config.get_config_value( |
| 'section2', 'opt6', |
| allow_blank=True, default='').AndReturn('blah') |
| self.mox.ReplayAll() |
| shadow_config = moblab_rpc_interface._get_shadow_config_from_partial_update( |
| partial_config) |
| # opt2 is still in shadow |
| self.assertEquals('value2_1', shadow_config.get('section1', 'opt2')) |
| # opt5 is not changed. |
| self.assertFalse(shadow_config.has_option('section2', 'opt5')) |
| # opt6 is updated. |
| self.assertEquals('value6', shadow_config.get('section2', 'opt6')) |
| self.mox.VerifyAll() |
| |
| def testGetBuildsForInDirectory(self): |
| config_mock = self.mox.CreateMockAnything() |
| moblab_rpc_interface._CONFIG = config_mock |
| config_mock.get_config_value( |
| 'CROS', 'image_storage_server').AndReturn('gs://bucket1/') |
| self.mox.StubOutWithMock(common_lib_utils, 'run') |
| output = self.mox.CreateMockAnything() |
| self.mox.StubOutWithMock(StringIO, 'StringIO', use_mock_anything=True) |
| StringIO.StringIO().AndReturn(output) |
| output.getvalue().AndReturn( |
| """gs://bucket1/dummy/R53-8480.0.0/\ngs://bucket1/dummy/R53-8530.72.0/\n |
| gs://bucket1/dummy/R54-8712.0.0/\ngs://bucket1/dummy/R54-8717.0.0/\n |
| gs://bucket1/dummy/R55-8759.0.0/\n |
| gs://bucket1/dummy/R55-8760.0.0-b5849/\n |
| gs://bucket1/dummy/R56-8995.0.0/\ngs://bucket1/dummy/R56-9001.0.0/\n |
| gs://bucket1/dummy/R57-9202.66.0/\ngs://bucket1/dummy/R58-9331.0.0/\n |
| gs://bucket1/dummy/R58-9334.15.0/\ngs://bucket1/dummy/R58-9334.17.0/\n |
| gs://bucket1/dummy/R58-9334.18.0/\ngs://bucket1/dummy/R58-9334.19.0/\n |
| gs://bucket1/dummy/R58-9334.22.0/\ngs://bucket1/dummy/R58-9334.28.0/\n |
| gs://bucket1/dummy/R58-9334.3.0/\ngs://bucket1/dummy/R58-9334.30.0/\n |
| gs://bucket1/dummy/R58-9334.36.0/\ngs://bucket1/dummy/R58-9334.55.0/\n |
| gs://bucket1/dummy/R58-9334.6.0/\ngs://bucket1/dummy/R58-9334.7.0/\n |
| gs://bucket1/dummy/R58-9334.9.0/\ngs://bucket1/dummy/R59-9346.0.0/\n |
| gs://bucket1/dummy/R59-9372.0.0/\ngs://bucket1/dummy/R59-9387.0.0/\n |
| gs://bucket1/dummy/R59-9436.0.0/\ngs://bucket1/dummy/R59-9452.0.0/\n |
| gs://bucket1/dummy/R59-9453.0.0/\ngs://bucket1/dummy/R59-9455.0.0/\n |
| gs://bucket1/dummy/R59-9460.0.0/\ngs://bucket1/dummy/R59-9460.11.0/\n |
| gs://bucket1/dummy/R59-9460.16.0/\ngs://bucket1/dummy/R59-9460.25.0/\n |
| gs://bucket1/dummy/R59-9460.8.0/\ngs://bucket1/dummy/R59-9460.9.0/\n |
| gs://bucket1/dummy/R60-9472.0.0/\ngs://bucket1/dummy/R60-9491.0.0/\n |
| gs://bucket1/dummy/R60-9492.0.0/\ngs://bucket1/dummy/R60-9497.0.0/\n |
| gs://bucket1/dummy/R60-9500.0.0/""") |
| |
| output.close() |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.GsUtil, 'get_gsutil_cmd') |
| moblab_rpc_interface.GsUtil.get_gsutil_cmd().AndReturn( |
| '/path/to/gsutil') |
| |
| common_lib_utils.run('/path/to/gsutil', |
| args=('ls', 'gs://bucket1/dummy'), |
| stdout_tee=mox.IgnoreArg()).AndReturn(output) |
| self.mox.ReplayAll() |
| expected_results = ['dummy/R60-9500.0.0', 'dummy/R60-9497.0.0', |
| 'dummy/R60-9492.0.0', 'dummy/R60-9491.0.0', 'dummy/R60-9472.0.0', |
| 'dummy/R59-9460.25.0', 'dummy/R59-9460.16.0', 'dummy/R59-9460.11.0', |
| 'dummy/R59-9460.9.0', 'dummy/R59-9460.8.0', 'dummy/R58-9334.55.0', |
| 'dummy/R58-9334.36.0', 'dummy/R58-9334.30.0', 'dummy/R58-9334.28.0', |
| 'dummy/R58-9334.22.0'] |
| actual_results = moblab_rpc_interface._get_builds_for_in_directory( |
| "dummy",3, 5) |
| self.assertEquals(expected_results, actual_results) |
| self.mox.VerifyAll() |
| |
| def testRunBucketPerformanceTestFail(self): |
| self.mox.StubOutWithMock(moblab_rpc_interface.GsUtil, 'get_gsutil_cmd') |
| moblab_rpc_interface.GsUtil.get_gsutil_cmd().AndReturn( |
| '/path/to/gsutil') |
| self.mox.StubOutWithMock(common_lib_utils, 'run') |
| common_lib_utils.run('/path/to/gsutil', |
| args=( |
| '-o', 'Credentials:gs_access_key_id=key', |
| '-o', 'Credentials:gs_secret_access_key=secret', |
| 'perfdiag', '-s', '1K', |
| '-o', 'testoutput', |
| '-n', '10', |
| 'gs://bucket1')).AndRaise( |
| error.CmdError("fakecommand", common_lib_utils.CmdResult(), |
| "xxxxxx<Error>yyyyyyyyyy</Error>")) |
| |
| self.mox.ReplayAll() |
| self.assertRaisesRegexp( |
| moblab_rpc_interface.BucketPerformanceTestException, |
| '<Error>yyyyyyyyyy', |
| moblab_rpc_interface._run_bucket_performance_test, |
| 'key', 'secret', 'gs://bucket1', '1K', '10', 'testoutput') |
| self.mox.VerifyAll() |
| |
| def testEnableNotificationUsingCredentialsInBucketFail(self): |
| config_mock = self.mox.CreateMockAnything() |
| moblab_rpc_interface._CONFIG = config_mock |
| config_mock.get_config_value( |
| 'CROS', 'image_storage_server').AndReturn('gs://bucket1/') |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.GsUtil, 'get_gsutil_cmd') |
| moblab_rpc_interface.GsUtil.get_gsutil_cmd().AndReturn( |
| '/path/to/gsutil') |
| |
| self.mox.StubOutWithMock(common_lib_utils, 'run') |
| common_lib_utils.run('/path/to/gsutil', |
| args=('cp', 'gs://bucket1/pubsub-key-do-not-delete.json', |
| '/tmp')).AndRaise( |
| error.CmdError("fakecommand", common_lib_utils.CmdResult(), "")) |
| self.mox.ReplayAll() |
| moblab_rpc_interface._enable_notification_using_credentials_in_bucket() |
| |
| def testEnableNotificationUsingCredentialsInBucketSuccess(self): |
| config_mock = self.mox.CreateMockAnything() |
| moblab_rpc_interface._CONFIG = config_mock |
| config_mock.get_config_value( |
| 'CROS', 'image_storage_server').AndReturn('gs://bucket1/') |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.GsUtil, 'get_gsutil_cmd') |
| moblab_rpc_interface.GsUtil.get_gsutil_cmd().AndReturn( |
| '/path/to/gsutil') |
| |
| self.mox.StubOutWithMock(common_lib_utils, 'run') |
| common_lib_utils.run('/path/to/gsutil', |
| args=('cp', 'gs://bucket1/pubsub-key-do-not-delete.json', |
| '/tmp')) |
| moblab_rpc_interface.shutil = self.mox.CreateMockAnything() |
| moblab_rpc_interface.shutil.copyfile( |
| '/tmp/pubsub-key-do-not-delete.json', |
| moblab_host.MOBLAB_SERVICE_ACCOUNT_LOCATION) |
| self.mox.StubOutWithMock(moblab_rpc_interface, '_update_partial_config') |
| moblab_rpc_interface._update_partial_config( |
| {'CROS': [(moblab_rpc_interface._CLOUD_NOTIFICATION_ENABLED, True)]} |
| ) |
| self.mox.ReplayAll() |
| moblab_rpc_interface._enable_notification_using_credentials_in_bucket() |
| |
| def testInstallSystemUpdate(self): |
| update_engine_client = moblab_rpc_interface._UPDATE_ENGINE_CLIENT |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.subprocess, 'check_call') |
| moblab_rpc_interface.subprocess.check_call(['sudo', |
| update_engine_client, '--update']) |
| moblab_rpc_interface.subprocess.check_call(['sudo', |
| update_engine_client, '--is_reboot_needed']) |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.subprocess, 'call') |
| moblab_rpc_interface.subprocess.call(['sudo', update_engine_client, |
| '--reboot']) |
| |
| self.mox.ReplayAll() |
| moblab_rpc_interface._install_system_update() |
| |
| def testInstallSystemUpdateError(self): |
| update_engine_client = moblab_rpc_interface._UPDATE_ENGINE_CLIENT |
| |
| error_message = ('ERROR_CODE=37\n' |
| 'ERROR_MESSAGE=ErrorCode::kOmahaErrorInHTTPResponse') |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.subprocess, 'check_call') |
| moblab_rpc_interface.subprocess.check_call(['sudo', |
| update_engine_client, '--update']).AndRaise( |
| moblab_rpc_interface.subprocess.CalledProcessError(1, |
| 'sudo')) |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.subprocess, |
| 'check_output') |
| moblab_rpc_interface.subprocess.check_output(['sudo', |
| update_engine_client, '--last_attempt_error']).AndReturn( |
| error_message) |
| |
| self.mox.ReplayAll() |
| try: |
| moblab_rpc_interface._install_system_update() |
| except moblab_rpc_interface.error.RPCException as e: |
| self.assertEquals(str(e), error_message) |
| |
| |
| def testGetSystemUpdateStatus(self): |
| update_engine_client = moblab_rpc_interface._UPDATE_ENGINE_CLIENT |
| update_status = ('LAST_CHECKED_TIME=1516753795\n' |
| 'PROGRESS=0.220121\n' |
| 'CURRENT_OP=UPDATE_STATUS_DOWNLOADING\n' |
| 'NEW_VERSION=10032.89.0\n' |
| 'NEW_SIZE=782805733') |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.subprocess, |
| 'check_output') |
| moblab_rpc_interface.subprocess.check_output(['sudo', |
| update_engine_client, '--status']).AndReturn( |
| update_status) |
| |
| self.mox.ReplayAll() |
| output = moblab_rpc_interface._get_system_update_status() |
| |
| self.assertEquals(output['PROGRESS'], '0.220121') |
| self.assertEquals(output['CURRENT_OP'], 'UPDATE_STATUS_DOWNLOADING') |
| self.assertEquals(output['NEW_VERSION'], '10032.89.0') |
| self.assertEquals(output['NEW_SIZE'], '782805733') |
| |
| def testCheckForSystemUpdate(self): |
| update_engine_client = moblab_rpc_interface._UPDATE_ENGINE_CLIENT |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.subprocess, 'call') |
| moblab_rpc_interface.subprocess.call(['sudo', update_engine_client, |
| '--check_for_update']) |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface, |
| '_get_system_update_status') |
| for i in range(0,4): |
| moblab_rpc_interface._get_system_update_status().AndReturn( |
| dict({'CURRENT_OP': 'UPDATE_STATUS_CHECKING_FOR_UPDATE'}) |
| ) |
| moblab_rpc_interface._get_system_update_status().AndReturn( |
| dict({'CURRENT_OP': 'UPDATE_STATUS_DOWNLOADING'}) |
| ) |
| self.mox.ReplayAll() |
| moblab_rpc_interface._check_for_system_update() |
| |
| def testGetConnectedDutBoardModels(self): |
| # setting up mocks for 2 duts with different boards and models |
| mock_minnie_labels = [ |
| self.mox.CreateMockAnything(), |
| self.mox.CreateMockAnything(), |
| ] |
| mock_minnie_labels[0].name = 'board:veyron_minnie' |
| mock_minnie_labels[1].name = 'model:veyron_minnie' |
| mock_minnie = self.mox.CreateMockAnything() |
| mock_minnie.label_list = mock_minnie_labels |
| |
| mock_bruce_labels = [ |
| self.mox.CreateMockAnything(), |
| self.mox.CreateMockAnything() |
| ] |
| mock_bruce_labels[0].name = 'board:carl' |
| mock_bruce_labels[1].name = 'model:bruce' |
| mock_bruce = self.mox.CreateMockAnything() |
| mock_bruce.label_list = mock_bruce_labels |
| hosts = [mock_minnie, mock_bruce] |
| |
| # stub out the host query calls |
| self.mox.StubOutWithMock(moblab_rpc_interface.rpc_utils, |
| 'get_host_query') |
| moblab_rpc_interface.rpc_utils.get_host_query( |
| (), False, True, {}).AndReturn(hosts) |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.models.Host.objects, |
| 'populate_relationships'), |
| moblab_rpc_interface.models.Host.objects.populate_relationships(hosts, |
| moblab_rpc_interface.models.Label, 'label_list') |
| |
| expected = [{ |
| 'model': 'bruce', |
| 'board': 'carl' |
| }, |
| { |
| 'model': 'veyron_minnie', |
| 'board': 'veyron_minnie' |
| }] |
| |
| self.mox.ReplayAll() |
| output = moblab_rpc_interface._get_connected_dut_board_models() |
| self.assertEquals(output, expected) |
| # test sorting |
| self.assertEquals(output[0]['model'], 'bruce') |
| |
| def testAllDutConnections(self): |
| leases = { |
| '192.168.0.20': '3c:52:82:5f:15:20', |
| '192.168.0.30': '3c:52:82:5f:15:21' |
| } |
| |
| # stub out all of the multiprocessing |
| mock_value = self.mox.CreateMockAnything() |
| mock_value.value = True |
| mock_process = self.mox.CreateMockAnything() |
| |
| for key in leases: |
| mock_process.start() |
| for key in leases: |
| mock_process.join() |
| |
| self.mox.StubOutWithMock( |
| moblab_rpc_interface, 'multiprocessing') |
| |
| for key in leases: |
| moblab_rpc_interface.multiprocessing.Value( |
| mox.IgnoreArg()).AndReturn(mock_value) |
| moblab_rpc_interface.multiprocessing.Process( |
| target=mox.IgnoreArg(), args=mox.IgnoreArg()).AndReturn( |
| mock_process) |
| |
| self.mox.ReplayAll() |
| |
| expected = { |
| '192.168.0.20': { |
| 'mac_address': '3c:52:82:5f:15:20', |
| 'ssh_connection_ok': True |
| }, |
| '192.168.0.30': { |
| 'mac_address': '3c:52:82:5f:15:21', |
| 'ssh_connection_ok': True |
| } |
| } |
| |
| connected_duts = moblab_rpc_interface._test_all_dut_connections(leases) |
| self.assertDictEqual(expected, connected_duts) |
| |
| def testAllDutConnectionsFailure(self): |
| leases = { |
| '192.168.0.20': '3c:52:82:5f:15:20', |
| '192.168.0.30': '3c:52:82:5f:15:21' |
| } |
| |
| # stub out all of the multiprocessing |
| mock_value = self.mox.CreateMockAnything() |
| mock_value.value = False |
| mock_process = self.mox.CreateMockAnything() |
| |
| for key in leases: |
| mock_process.start() |
| for key in leases: |
| mock_process.join() |
| |
| self.mox.StubOutWithMock( |
| moblab_rpc_interface, 'multiprocessing') |
| |
| for key in leases: |
| moblab_rpc_interface.multiprocessing.Value( |
| mox.IgnoreArg()).AndReturn(mock_value) |
| moblab_rpc_interface.multiprocessing.Process( |
| target=mox.IgnoreArg(), args=mox.IgnoreArg()).AndReturn( |
| mock_process) |
| |
| self.mox.ReplayAll() |
| |
| expected = { |
| '192.168.0.20': { |
| 'mac_address': '3c:52:82:5f:15:20', |
| 'ssh_connection_ok': False |
| }, |
| '192.168.0.30': { |
| 'mac_address': '3c:52:82:5f:15:21', |
| 'ssh_connection_ok': False |
| } |
| } |
| |
| connected_duts = moblab_rpc_interface._test_all_dut_connections(leases) |
| self.assertDictEqual(expected, connected_duts) |
| |
| def testDutSshConnection(self): |
| good_ip = '192.168.0.20' |
| bad_ip = '192.168.0.30' |
| cmd = ('ssh -o ConnectTimeout=3 -o StrictHostKeyChecking=no ' |
| "root@%s 'timeout 2 cat /etc/lsb-release'") |
| |
| self.mox.StubOutWithMock(moblab_rpc_interface.subprocess, |
| 'check_output') |
| moblab_rpc_interface.subprocess.check_output( |
| cmd % good_ip, shell=True).AndReturn('CHROMEOS_RELEASE_APPID') |
| |
| moblab_rpc_interface.subprocess.check_output( |
| cmd % bad_ip, shell=True).AndRaise( |
| moblab_rpc_interface.subprocess.CalledProcessError(1, cmd)) |
| |
| self.mox.ReplayAll() |
| self.assertEquals( |
| moblab_rpc_interface._test_dut_ssh_connection(good_ip), True) |
| self.assertEquals( |
| moblab_rpc_interface._test_dut_ssh_connection(bad_ip), False) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |