| # -*- coding: utf-8 -*- |
| # Copyright 2018 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. |
| |
| """Unittests for buildstore library.""" |
| |
| from __future__ import print_function |
| |
| import mock |
| |
| from chromite.lib import cidb |
| from chromite.lib import constants |
| from chromite.lib import cros_test_lib |
| from chromite.lib import buildstore |
| from chromite.lib import buildbucket_v2 |
| |
| BuildStore = buildstore.BuildStore |
| |
| |
| class TestBuildStore(cros_test_lib.MockTestCase): |
| """Test buildstore.BuildStore.""" |
| |
| def testIsCIDBClientMissing(self): |
| """Tests _IsCIDBClientMissing function.""" |
| # pylint: disable=protected-access |
| # Test CIDB needed and client missing. |
| bs = BuildStore(_read_from_bb=False, _write_to_cidb=True) |
| self.assertEqual(bs._IsCIDBClientMissing(), True) |
| bs = BuildStore(_read_from_bb=True, _write_to_cidb=True) |
| self.assertEqual(bs._IsCIDBClientMissing(), True) |
| bs = BuildStore(_read_from_bb=False, _write_to_cidb=False) |
| self.assertEqual(bs._IsCIDBClientMissing(), True) |
| # Test CIDB is needed and client is up and running. |
| bs = BuildStore(_read_from_bb=False, _write_to_cidb=True) |
| bs.cidb_conn = object() |
| self.assertEqual(bs._IsCIDBClientMissing(), False) |
| bs = BuildStore(_read_from_bb=True, _write_to_cidb=True) |
| bs.cidb_conn = object() |
| self.assertEqual(bs._IsCIDBClientMissing(), False) |
| bs = BuildStore(_read_from_bb=False, _write_to_cidb=False) |
| bs.cidb_conn = object() |
| self.assertEqual(bs._IsCIDBClientMissing(), False) |
| # Test CIDB is not needed. |
| bs = BuildStore(_read_from_bb=True, _write_to_cidb=False) |
| self.assertEqual(bs._IsCIDBClientMissing(), False) |
| |
| def testIsBuildbucketClientMissing(self): |
| """Tests _IsBuildbucketClientMissing function.""" |
| # pylint: disable=protected-access |
| # Test Buildbucket needed and client missing. |
| bs = BuildStore(_read_from_bb=True, _write_to_bb=True) |
| self.assertEqual(bs._IsBuildbucketClientMissing(), True) |
| bs = BuildStore(_read_from_bb=True, _write_to_bb=False) |
| self.assertEqual(bs._IsBuildbucketClientMissing(), True) |
| bs = BuildStore(_read_from_bb=False, _write_to_bb=True) |
| self.assertEqual(bs._IsBuildbucketClientMissing(), True) |
| # Test Buildbucket is needed and client is up and running. |
| bs = BuildStore(_read_from_bb=True, _write_to_bb=True) |
| bs.bb_client = object() |
| self.assertEqual(bs._IsBuildbucketClientMissing(), False) |
| bs = BuildStore(_read_from_bb=False, _write_to_bb=True) |
| bs.bb_client = object() |
| self.assertEqual(bs._IsBuildbucketClientMissing(), False) |
| bs = BuildStore(_read_from_bb=True, _write_to_bb=False) |
| bs.bb_client = object() |
| self.assertEqual(bs._IsBuildbucketClientMissing(), False) |
| # Test Buildbucket is not needed. |
| bs = BuildStore(_read_from_bb=False, _write_to_bb=False) |
| self.assertEqual(bs._IsBuildbucketClientMissing(), False) |
| |
| def testInitializeClientsWithCIDBSetup(self): |
| """Tests InitializeClients with mock CIDB.""" |
| |
| class DummyCIDBConnection(object): |
| """Dummy class representing CIDBConnection.""" |
| |
| # With CIDB setup, cidb_conn is populated. |
| self.PatchObject(cidb.CIDBConnectionFactory, 'IsCIDBSetup', |
| return_value=True) |
| mock_cidb = DummyCIDBConnection() |
| self.PatchObject(cidb.CIDBConnectionFactory, |
| 'GetCIDBConnectionForBuilder', |
| return_value=mock_cidb) |
| bs = BuildStore() |
| result = bs.InitializeClients() |
| self.assertEqual(bs.cidb_conn, mock_cidb) |
| self.assertEqual(result, True) |
| |
| def testInitializeClientsWithoutCIDBSetup(self): |
| """Tests InitializeClients with mock CIDB.""" |
| |
| self.PatchObject(cidb.CIDBConnectionFactory, 'IsCIDBSetup', |
| return_value=False) |
| bs = BuildStore() |
| self.assertEqual(bs.InitializeClients(), False) |
| |
| def testInitializeClientsWhenCIDBIsNotNeeded(self): |
| """Test InitializeClients without CIDB requirement.""" |
| bs = BuildStore(_read_from_bb=True, _write_to_cidb=False) |
| bs.cidb_conn = None |
| self.PatchObject(BuildStore, '_IsBuildbucketClientMissing', |
| return_value=False) |
| # Does not raise exception. |
| self.assertEqual(bs.InitializeClients(), True) |
| |
| def testInitializeClientsWithBuildbucketSetup(self): |
| """Tests InitializeClients with mock Buildbucket.""" |
| bs = BuildStore() |
| self.PatchObject(bs, '_IsCIDBClientMissing', |
| return_value=False) |
| result = bs.InitializeClients() |
| self.assertTrue(isinstance(bs.bb_client, buildbucket_v2.BuildbucketV2)) |
| self.assertEqual(result, True) |
| |
| def testInitializeClientsWhenBuildbucketIsNotNeeded(self): |
| """Test InitializeClients without Buildbucket requirement.""" |
| bs = BuildStore(_read_from_bb=False, _write_to_bb=False) |
| self.PatchObject(BuildStore, '_IsCIDBClientMissing', |
| return_value=False) |
| # Does not raise exception. |
| self.assertEqual(bs.InitializeClients(), True) |
| |
| def testInsertBuild(self): |
| """Tests the redirect for InsertBuild function.""" |
| self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| # Test CIDB redirect. |
| bs = BuildStore(_write_to_cidb=True, _write_to_bb=False) |
| bs.cidb_conn = mock.MagicMock() |
| self.PatchObject(bs.cidb_conn, 'InsertBuild', |
| return_value=constants.MOCK_BUILD_ID) |
| build_id = bs.InsertBuild( |
| 'builder_name', 12345, |
| 'something-paladin', 'bot_hostname', master_build_id='master_id', |
| timeout_seconds='timeout') |
| bs.cidb_conn.InsertBuild.assert_called_once_with( |
| 'builder_name', 12345, 'something-paladin', 'bot_hostname', |
| 'master_id', 'timeout', None, None, None) |
| self.assertEqual(build_id, constants.MOCK_BUILD_ID) |
| # Test Buildbucket redirect. |
| bs = BuildStore(_write_to_cidb=False, _write_to_bb=True) |
| bs.bb_client = mock.MagicMock() |
| self.PatchObject(buildbucket_v2, 'UpdateSelfCommonBuildProperties') |
| build_id = bs.InsertBuild( |
| 'builder_name', 12345, |
| 'something-paladin', 'bot_hostname', important=True, |
| timeout_seconds='timeout') |
| buildbucket_v2.UpdateSelfCommonBuildProperties.assert_called_once_with( |
| critical=True) |
| self.assertEqual(build_id, 0) |
| |
| def testInsertBuildStage(self): |
| """Tests the redirect for InsertBuildStage function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| self.PatchObject(bs.cidb_conn, 'InsertBuildStage', |
| return_value=constants.MOCK_STAGE_ID) |
| build_stage_id = bs.InsertBuildStage( |
| constants.MOCK_BUILD_ID, 'stage_name') |
| bs.cidb_conn.InsertBuildStage.assert_called_once_with( |
| constants.MOCK_BUILD_ID, 'stage_name', None, |
| constants.BUILDER_STATUS_PLANNED) |
| self.assertEqual(build_stage_id, constants.MOCK_STAGE_ID) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.InsertBuildStage(constants.MOCK_BUILD_ID, 'stage_name') |
| |
| def testStartBuildStage(self): |
| """Tests the redirect for StartBuildStage function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| stage_id = mock.Mock() |
| self.PatchObject(bs.cidb_conn, 'StartBuildStage', return_value=stage_id) |
| ret = bs.StartBuildStage(constants.MOCK_BUILD_ID) |
| bs.cidb_conn.StartBuildStage.assert_called_once_with( |
| constants.MOCK_BUILD_ID) |
| self.assertEqual(ret, stage_id) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.StartBuildStage(constants.MOCK_BUILD_ID) |
| |
| def testWaitBuildStage(self): |
| """Tests the redirect for WaitBuildStage function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| stage_id = mock.Mock() |
| self.PatchObject(bs.cidb_conn, 'WaitBuildStage', return_value=stage_id) |
| ret = bs.WaitBuildStage(constants.MOCK_BUILD_ID) |
| bs.cidb_conn.WaitBuildStage.assert_called_once_with( |
| constants.MOCK_BUILD_ID) |
| self.assertEqual(ret, stage_id) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.WaitBuildStage(constants.MOCK_BUILD_ID) |
| |
| def testFinishBuildStage(self): |
| """Tests the redirect for FinishBuildStage function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| stage_id = mock.Mock() |
| self.PatchObject(bs.cidb_conn, 'FinishBuildStage', return_value=stage_id) |
| ret = bs.FinishBuildStage(constants.MOCK_BUILD_ID, 'status') |
| bs.cidb_conn.FinishBuildStage.assert_called_once_with( |
| constants.MOCK_BUILD_ID, 'status') |
| self.assertEqual(ret, stage_id) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.FinishBuildStage(constants.MOCK_BUILD_ID, 'status') |
| |
| def testInsertFailure(self): |
| """Tests the redirect for InsertFailure function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| self.PatchObject(bs.cidb_conn, 'InsertFailure') |
| bs.InsertFailure( |
| constants.MOCK_STAGE_ID, 'error_type', 'SomethingFailedException') |
| bs.cidb_conn.InsertFailure.assert_called_once_with( |
| constants.MOCK_STAGE_ID, 'error_type', 'SomethingFailedException', |
| constants.EXCEPTION_CATEGORY_UNKNOWN, None, None) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.InsertFailure(constants.MOCK_STAGE_ID, 'error_type', |
| 'SomethingFailedException') |
| |
| def testFinishBuild(self): |
| """Tests the redirect for FinishBuild function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| status = mock.Mock() |
| summary = mock.Mock() |
| metadata_url = mock.Mock() |
| strict = mock.Mock() |
| self.PatchObject(bs.cidb_conn, 'FinishBuild') |
| bs.FinishBuild(constants.MOCK_BUILD_ID, status=status, summary=summary, |
| metadata_url=metadata_url, strict=strict) |
| bs.cidb_conn.FinishBuild.assert_called_once_with( |
| constants.MOCK_BUILD_ID, status=status, summary=summary, |
| metadata_url=metadata_url, strict=strict) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.FinishBuild(constants.MOCK_BUILD_ID, status=status, summary=summary, |
| metadata_url=metadata_url, strict=strict) |
| |
| def testFinishChildConfig(self): |
| """Tests the redirect for FinishChildConfig function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| child_config = mock.Mock() |
| status = mock.Mock() |
| self.PatchObject(bs.cidb_conn, 'FinishChildConfig') |
| bs.FinishChildConfig(constants.MOCK_BUILD_ID, child_config, status=status) |
| bs.cidb_conn.FinishChildConfig.assert_called_once_with( |
| constants.MOCK_BUILD_ID, child_config, status=status) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.FinishChildConfig(constants.MOCK_BUILD_ID, child_config, status=status) |
| |
| def testUpdateMetadata(self): |
| """Tests the redirect for UpdateMetadata function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore(_write_to_cidb=True, _write_to_bb=False) |
| bs.cidb_conn = mock.MagicMock() |
| fake_metadata = {} |
| self.PatchObject(bs.cidb_conn, 'UpdateMetadata') |
| bs.UpdateMetadata(constants.MOCK_BUILD_ID, fake_metadata) |
| bs.cidb_conn.UpdateMetadata.assert_called_once_with( |
| constants.MOCK_BUILD_ID, fake_metadata) |
| bs = BuildStore(_write_to_cidb=False, _write_to_bb=True) |
| self.PatchObject(buildbucket_v2, 'UpdateBuildMetadata') |
| bs.UpdateMetadata(constants.MOCK_BUILD_ID, fake_metadata) |
| buildbucket_v2.UpdateBuildMetadata.assert_called_once_with(fake_metadata) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.UpdateMetadata(constants.MOCK_BUILD_ID, fake_metadata) |
| |
| def testGetBuildsFailures(self): |
| """Tests the redirect for GetBuildsFailures function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| buildbucket_ids = ['bucket 1', 'bucket 2'] |
| # Test for buildbucket_ids. |
| bs.GetBuildsFailures(buildbucket_ids=buildbucket_ids) |
| bs.cidb_conn.GetBuildsFailures.assert_called_once_with( |
| buildbucket_ids) |
| # Test for empty argument. |
| self.assertEqual(bs.GetBuildsFailures([]), []) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.GetBuildsFailures(buildbucket_ids=buildbucket_ids) |
| |
| def testGetBuildsStages(self): |
| """Tests the redirect for GetBuildsStages function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| build_ids = ['build 1', 'build 2'] |
| buildbucket_ids = ['bucket 1', 'bucket 2'] |
| # Test for buildbucket_ids. |
| bs.GetBuildsStages(buildbucket_ids=buildbucket_ids) |
| bs.cidb_conn.GetBuildsStagesWithBuildbucketIds.assert_called_once_with( |
| buildbucket_ids) |
| # Test for build_ids. |
| bs.GetBuildsStages(build_ids=build_ids) |
| bs.cidb_conn.GetBuildsStages.assert_called_once_with(build_ids) |
| # Test for neither arguments. |
| self.assertEqual(bs.GetBuildsStages(), []) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.GetBuildsStages(build_ids=build_ids) |
| |
| def testExtendDeadline(self): |
| """Tests the redirect for ExtendDeadline function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| mock_timeout = mock.Mock() |
| self.PatchObject(bs.cidb_conn, 'ExtendDeadline') |
| bs.ExtendDeadline(constants.MOCK_BUILD_ID, mock_timeout) |
| bs.cidb_conn.ExtendDeadline.assert_called_once_with( |
| constants.MOCK_BUILD_ID, mock_timeout) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.ExtendDeadline(constants.MOCK_BUILD_ID, mock_timeout) |
| |
| def testGetBuildStatuses(self): |
| """Tests the redirect for GetBuildStatuses function.""" |
| init = self.PatchObject(BuildStore, 'InitializeClients', |
| return_value=True) |
| bs = BuildStore() |
| bs.cidb_conn = mock.MagicMock() |
| build_ids = ['build 1', 'build 2'] |
| buildbucket_ids = ['bucket 1', 'bucket 2'] |
| # Test for buildbucket_ids. |
| bs.GetBuildStatuses(buildbucket_ids) |
| bs.cidb_conn.GetBuildStatusesWithBuildbucketIds.assert_called_once_with( |
| buildbucket_ids) |
| # Test for build_ids. |
| bs.GetBuildStatuses(build_ids=build_ids) |
| bs.cidb_conn.GetBuildStatuses.assert_called_once_with(build_ids) |
| # Test for neither arguments. |
| self.assertEqual(bs.GetBuildStatuses(), []) |
| init.return_value = False |
| with self.assertRaises(buildstore.BuildStoreException): |
| bs.GetBuildStatuses(build_ids=build_ids) |