#   Licensed under the Apache License, Version 2.0 (the "License"); you may
#   not use this file except in compliance with the License. You may obtain
#   a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#   License for the specific language governing permissions and limitations
#   under the License.
#
from unittest import mock

from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib import utils as oscutils

from manilaclient import api_versions
from manilaclient.common import cliutils

from manilaclient.osc import utils
from manilaclient.osc.v2 import share_replicas as osc_share_replicas

from manilaclient.tests.unit.osc import osc_utils
from manilaclient.tests.unit.osc.v2 import fakes as manila_fakes


class TestShareReplica(manila_fakes.TestShare):
    def setUp(self):
        super().setUp()

        self.shares_mock = self.app.client_manager.share.shares
        self.shares_mock.reset_mock()

        self.replicas_mock = self.app.client_manager.share.share_replicas
        self.replicas_mock.reset_mock()
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            api_versions.MAX_VERSION
        )

        self.replica_el_mock = (
            self.app.client_manager.share.share_replica_export_locations
        )
        self.replica_el_mock.reset_mock()


class TestShareReplicaCreate(TestShareReplica):
    def setUp(self):
        super().setUp()

        self.share = manila_fakes.FakeShare.create_one_share()
        self.shares_mock.get.return_value = self.share

        self.share_replica = manila_fakes.FakeShareReplica.create_one_replica(
            attrs={'availability_zone': 'manila-zone-1', 'status': 'available'}
        )
        self.replicas_mock.create.return_value = self.share_replica
        self.replicas_mock.get.return_value = self.share_replica

        self.cmd = osc_share_replicas.CreateShareReplica(self.app, None)

        self.data = tuple(self.share_replica._info.values())
        self.columns = tuple(self.share_replica._info.keys())

    def test_share_replica_create_missing_args(self):
        arglist = []
        verifylist = []

        self.assertRaises(
            osc_utils.ParserException,
            self.check_parser,
            self.cmd,
            arglist,
            verifylist,
        )

    def test_share_replica_create(self):
        arglist = [self.share.id]
        verifylist = [('share', self.share.id)]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)

        self.replicas_mock.create.assert_called_with(
            share=self.share, availability_zone=None
        )

        self.assertCountEqual(self.columns, columns)
        self.assertCountEqual(self.data, data)

    def test_share_replica_create_az(self):
        arglist = [
            self.share.id,
            '--availability-zone',
            self.share.availability_zone,
        ]
        verifylist = [
            ('share', self.share.id),
            ('availability_zone', self.share.availability_zone),
        ]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)

        self.replicas_mock.create.assert_called_with(
            share=self.share, availability_zone=self.share.availability_zone
        )

        self.assertCountEqual(self.columns, columns)
        self.assertCountEqual(self.data, data)

    def test_share_replica_create_scheduler_hint_valid(self):
        arglist = [
            self.share.id,
            '--availability-zone',
            self.share.availability_zone,
            '--scheduler-hint',
            ('only_host=host1@backend1#pool1'),
        ]
        verifylist = [
            ('share', self.share.id),
            ('availability_zone', self.share.availability_zone),
            ('scheduler_hint', {'only_host': 'host1@backend1#pool1'}),
        ]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)

        self.replicas_mock.create.assert_called_with(
            share=self.share,
            availability_zone=self.share.availability_zone,
            scheduler_hints={'only_host': 'host1@backend1#pool1'},
        )

        self.assertCountEqual(self.columns, columns)
        self.assertCountEqual(self.data, data)

    def test_share_replica_create_scheduler_hint_invalid_hint(self):
        arglist = [
            self.share.id,
            '--availability-zone',
            self.share.availability_zone,
            '--scheduler-hint',
            'fake_hint=host1@backend1#pool1',
        ]
        verifylist = [
            ('share', self.share.id),
            ('availability_zone', self.share.availability_zone),
            ('scheduler_hint', {'fake_hint': 'host1@backend1#pool1'}),
        ]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )

    def test_share_replica_create_scheduler_hint_invalid_version(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            "2.66"
        )

        arglist = [
            self.share.id,
            '--availability-zone',
            self.share.availability_zone,
            '--scheduler-hint',
            'only_host=host1@backend1#pool1',
        ]
        verifylist = [
            ('share', self.share.id),
            ('availability_zone', self.share.availability_zone),
            ('scheduler_hint', {'only_host': 'host1@backend1#pool1'}),
        ]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )

    def test_share_replica_create_share_network(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            "2.72"
        )

        arglist = [
            self.share.id,
            '--availability-zone',
            self.share.availability_zone,
            '--share-network',
            self.share.share_network_id,
        ]
        verifylist = [
            ('share', self.share.id),
            ('availability_zone', self.share.availability_zone),
            ('share_network', self.share.share_network_id),
        ]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)
        if self.share.share_network_id:
            self.replicas_mock.create.assert_called_with(
                share=self.share,
                availability_zone=self.share.availability_zone,
                share_network=self.share.share_network_id,
            )
        else:
            self.replicas_mock.create.assert_called_with(
                share=self.share,
                availability_zone=self.share.availability_zone,
            )

        self.assertCountEqual(self.columns, columns)
        self.assertCountEqual(self.data, data)

    def test_share_replica_create_with_metadata(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            "2.95"
        )

        arglist = [
            self.share.id,
            '--availability-zone',
            self.share.availability_zone,
            '--property',
            'fake_key1=fake_value1',
            '--property',
            'fake_key2=fake_value2',
        ]
        verifylist = [
            ('share', self.share.id),
            ('availability_zone', self.share.availability_zone),
            (
                'property',
                {'fake_key1': 'fake_value1', 'fake_key2': 'fake_value2'},
            ),
        ]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)

        self.replicas_mock.create.assert_called_with(
            share=self.share,
            availability_zone=self.share.availability_zone,
            metadata={'fake_key1': 'fake_value1', 'fake_key2': 'fake_value2'},
        )

        self.assertCountEqual(self.columns, columns)
        self.assertCountEqual(self.data, data)

    def test_share_replica_create_metadata_api_version_exception(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            '2.91'
        )
        arglist = [
            self.share.id,
            '--property',
            'fake_key=fake_value',
        ]
        verifylist = [
            ('share', self.share.id),
            ('property', {'fake_key': 'fake_value'}),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )

    def test_share_replica_create_wait(self):
        arglist = [self.share.id, '--wait']
        verifylist = [('share', self.share.id), ('wait', True)]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)

        self.replicas_mock.create.assert_called_with(
            share=self.share, availability_zone=None
        )

        self.replicas_mock.get.assert_called_with(self.share_replica.id)
        self.assertCountEqual(self.columns, columns)
        self.assertCountEqual(self.data, data)

    @mock.patch('manilaclient.osc.v2.share_replicas.LOG')
    def test_share_replica_create_wait_exception(self, mock_logger):
        arglist = [self.share.id, '--wait']
        verifylist = [('share', self.share.id), ('wait', True)]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        with mock.patch('osc_lib.utils.wait_for_status', return_value=False):
            columns, data = self.cmd.take_action(parsed_args)

            self.replicas_mock.create.assert_called_with(
                share=self.share, availability_zone=None
            )

            mock_logger.error.assert_called_with(
                "ERROR: Share replica is in error state."
            )

            self.replicas_mock.get.assert_called_with(self.share_replica.id)
            self.assertCountEqual(self.columns, columns)
            self.assertCountEqual(self.data, data)


class TestShareReplicaDelete(TestShareReplica):
    def setUp(self):
        super().setUp()

        self.share_replica = manila_fakes.FakeShareReplica.create_one_replica()
        self.replicas_mock.get.return_value = self.share_replica

        self.cmd = osc_share_replicas.DeleteShareReplica(self.app, None)

    def test_share_replica_delete_missing_args(self):
        arglist = []
        verifylist = []

        self.assertRaises(
            osc_utils.ParserException,
            self.check_parser,
            self.cmd,
            arglist,
            verifylist,
        )

    def test_share_replica_delete(self):
        arglist = [self.share_replica.id]
        verifylist = [('replica', [self.share_replica.id])]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        result = self.cmd.take_action(parsed_args)

        self.replicas_mock.delete.assert_called_with(
            self.share_replica, force=False
        )
        self.assertIsNone(result)

    def test_share_replica_delete_force(self):
        arglist = [self.share_replica.id, '--force']
        verifylist = [('replica', [self.share_replica.id]), ('force', True)]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        result = self.cmd.take_action(parsed_args)

        self.replicas_mock.delete.assert_called_with(
            self.share_replica, force=True
        )
        self.assertIsNone(result)

    def test_share_replica_delete_multiple(self):
        share_replicas = manila_fakes.FakeShareReplica.create_share_replicas(
            count=2
        )
        arglist = [share_replicas[0].id, share_replicas[1].id]
        verifylist = [
            ('replica', [share_replicas[0].id, share_replicas[1].id])
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        result = self.cmd.take_action(parsed_args)

        self.assertEqual(
            self.replicas_mock.delete.call_count, len(share_replicas)
        )
        self.assertIsNone(result)

    def test_share_snapshot_delete_exception(self):
        arglist = [self.share_replica.id]
        verifylist = [('replica', [self.share_replica.id])]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.replicas_mock.delete.side_effect = exceptions.CommandError()
        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )

    def test_share_replica_delete_wait(self):
        arglist = [self.share_replica.id, '--wait']
        verifylist = [('replica', [self.share_replica.id]), ('wait', True)]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        with mock.patch('osc_lib.utils.wait_for_delete', return_value=True):
            result = self.cmd.take_action(parsed_args)

            self.replicas_mock.delete.assert_called_with(
                self.share_replica, force=False
            )
            self.replicas_mock.get.assert_called_with(self.share_replica.id)
            self.assertIsNone(result)

    def test_share_replica_delete_wait_exception(self):
        arglist = [self.share_replica.id, '--wait']
        verifylist = [('replica', [self.share_replica.id]), ('wait', True)]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        with mock.patch('osc_lib.utils.wait_for_delete', return_value=False):
            self.assertRaises(
                exceptions.CommandError, self.cmd.take_action, parsed_args
            )


class TestShareReplicaList(TestShareReplica):
    columns = [
        'id',
        'status',
        'replica_state',
        'share_id',
        'host',
        'availability_zone',
        'updated_at',
        'properties',
    ]

    column_headers = utils.format_column_headers(columns)

    def setUp(self):
        super().setUp()

        self.share = manila_fakes.FakeShare.create_one_share()
        self.shares_mock.get.return_value = self.share

        self.replicas_list = (
            manila_fakes.FakeShareReplica.create_share_replicas(count=2)
        )
        self.replicas_mock.list.return_value = self.replicas_list

        self.values = (
            oscutils.get_dict_properties(i._info, self.columns)
            for i in self.replicas_list
        )

        self.cmd = osc_share_replicas.ListShareReplica(self.app, None)

    def test_share_replica_list(self):
        arglist = []
        verifylist = []

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)

        self.replicas_mock.list.assert_called_with(share=None, search_opts={})

        self.assertEqual(self.column_headers, columns)
        self.assertEqual(list(self.values), list(data))

    def test_share_replica_list_for_share(self):
        arglist = ['--share', self.share.id]
        verifylist = [('share', self.share.id)]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)

        self.replicas_mock.list.assert_called_with(
            share=self.share, search_opts={}
        )

        self.assertEqual(self.column_headers, columns)
        self.assertEqual(list(self.values), list(data))

    def test_share_replica_list_with_properties_column(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            "2.95"
        )
        metadata = {'replication_policy': 'Sync'}
        self.replicas_list = (
            manila_fakes.FakeShareReplica.create_share_replicas(
                attrs={'metadata': metadata}, count=2
            )
        )
        self.replicas_mock.list.return_value = self.replicas_list

        arglist = []
        verifylist = []
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)

        self.assertEqual(self.column_headers, columns)

        data_list = list(data)
        self.assertEqual(2, len(data_list))
        for row in data_list:
            props = row[-1]
            self.assertIsInstance(props, format_columns.DictColumn)
            self.assertEqual({'replication_policy': 'Sync'}, props._value)

    def test_share_replica_list_without_properties_column(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            "2.94"
        )
        arglist = []
        verifylist = []
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)

        self.assertNotIn('Properties', columns)


class TestShareReplicaShow(TestShareReplica):
    def setUp(self):
        super().setUp()

        self.share_replica = manila_fakes.FakeShareReplica.create_one_replica()
        self.replicas_mock.get.return_value = self.share_replica

        self.replica_el_list = (
            manila_fakes.FakeShareExportLocation.create_share_export_locations(
                count=2
            )
        )

        self.replica_el_mock.list.return_value = self.replica_el_list

        self.cmd = osc_share_replicas.ShowShareReplica(self.app, None)

        self.share_replica._info['export_locations'] = (
            cliutils.convert_dict_list_to_string(self.replica_el_list)
        )

        self.data = tuple(self.share_replica._info.values())
        self.columns = tuple(self.share_replica._info.keys())

    def test_share_replica_show_missing_args(self):
        arglist = []
        verifylist = []

        self.assertRaises(
            osc_utils.ParserException,
            self.check_parser,
            self.cmd,
            arglist,
            verifylist,
        )

    def test_share_replica_show(self):
        arglist = [self.share_replica.id]
        verifylist = [('replica', self.share_replica.id)]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        columns, data = self.cmd.take_action(parsed_args)

        self.replicas_mock.get.assert_called_with(self.share_replica.id)

        self.assertCountEqual(self.columns, columns)
        self.assertCountEqual(self.data, data)


class TestShareReplicaSet(TestShareReplica):
    def setUp(self):
        super().setUp()

        self.share_replica = manila_fakes.FakeShareReplica.create_one_replica(
            methods={"set_metadata": None}
        )
        self.replicas_mock.get.return_value = self.share_replica

        self.cmd = osc_share_replicas.SetShareReplica(self.app, None)

    def test_share_replica_set_replica_state(self):
        new_replica_state = 'in_sync'
        arglist = [self.share_replica.id, '--replica-state', new_replica_state]
        verifylist = [
            ('replica', self.share_replica.id),
            ('replica_state', new_replica_state),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        result = self.cmd.take_action(parsed_args)

        self.replicas_mock.reset_replica_state.assert_called_with(
            self.share_replica, new_replica_state
        )
        self.assertIsNone(result)

    def test_share_replica_set_replica_state_exception(self):
        new_replica_state = 'in_sync'
        arglist = [self.share_replica.id, '--replica-state', new_replica_state]
        verifylist = [
            ('replica', self.share_replica.id),
            ('replica_state', new_replica_state),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.replicas_mock.reset_replica_state.side_effect = Exception()

        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )

    def test_share_replica_set_status(self):
        new_status = 'available'
        arglist = [self.share_replica.id, '--status', new_status]
        verifylist = [
            ('replica', self.share_replica.id),
            ('status', new_status),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        result = self.cmd.take_action(parsed_args)

        self.replicas_mock.reset_state.assert_called_with(
            self.share_replica, new_status
        )
        self.assertIsNone(result)

    def test_share_replica_set_status_exception(self):
        new_status = 'available'
        arglist = [self.share_replica.id, '--status', new_status]
        verifylist = [
            ('replica', self.share_replica.id),
            ('status', new_status),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.replicas_mock.reset_state.side_effect = Exception()

        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )

    def test_share_replica_set_nothing_defined(self):
        arglist = [
            self.share_replica.id,
        ]
        verifylist = [
            ('replica', self.share_replica.id),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )

    def test_share_replica_set_property(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            '2.95'
        )
        arglist = [
            self.share_replica.id,
            '--property',
            'fake_key=fake_value',
        ]
        verifylist = [
            ('replica', self.share_replica.id),
            ('property', {'fake_key': 'fake_value'}),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.cmd.take_action(parsed_args)

        self.share_replica.set_metadata.assert_called_once_with(
            {'fake_key': 'fake_value'},
        )

    def test_share_replica_set_property_exception(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            '2.95'
        )
        arglist = [
            self.share_replica.id,
            '--property',
            'fake_key=fake_value',
        ]
        verifylist = [
            ('replica', self.share_replica.id),
            ('property', {'fake_key': 'fake_value'}),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.cmd.take_action(parsed_args)

        self.share_replica.set_metadata.assert_called_once_with(
            {'fake_key': 'fake_value'},
        )

        self.share_replica.set_metadata.side_effect = exceptions.BadRequest
        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )


class TestShareReplicaUnset(TestShareReplica):
    def setUp(self):
        super().setUp()

        self.share_replica = manila_fakes.FakeShareReplica.create_one_replica(
            methods={"delete_metadata": None}
        )
        self.replicas_mock.get.return_value = self.share_replica

        self.cmd = osc_share_replicas.UnsetShareReplica(self.app, None)

    def test_share_replica_unset_property(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            '2.95'
        )
        arglist = [
            '--property',
            'test_key',
            self.share_replica.id,
        ]
        verifylist = [
            ('property', ['test_key']),
            ('replica', self.share_replica.id),
        ]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.cmd.take_action(parsed_args)

        self.share_replica.delete_metadata.assert_called_once_with(
            parsed_args.property
        )

    def test_share_replica_unset_multiple_properties(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            '2.95'
        )
        arglist = [
            '--property',
            'key1',
            '--property',
            'key2',
            self.share_replica.id,
        ]
        verifylist = [
            ('property', ['key1', 'key2']),
            ('replica', self.share_replica.id),
        ]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.cmd.take_action(parsed_args)

        # Assert delete_metadata was called for each key
        expected_calls = [mock.call(['key1']), mock.call(['key2'])]
        self.share_replica.delete_metadata.assert_has_calls(
            expected_calls, any_order=False
        )
        self.assertEqual(self.share_replica.delete_metadata.call_count, 2)

    def test_share_replica_unset_property_exception(self):
        self.app.client_manager.share.api_version = api_versions.APIVersion(
            '2.95'
        )
        arglist = [
            self.share_replica.id,
            '--property',
            'test_key',
        ]
        verifylist = [
            ('replica', self.share_replica.id),
            ('property', ['test_key']),
        ]

        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        # 404 Not Found would be raised, if property 'test_key' doesn't exist.
        self.share_replica.delete_metadata.side_effect = exceptions.NotFound
        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )


class TestShareReplicaPromote(TestShareReplica):
    def setUp(self):
        super().setUp()

        self.share_replica = manila_fakes.FakeShareReplica.create_one_replica(
            attrs={'status': 'available'}
        )
        self.replicas_mock.get.return_value = self.share_replica

        self.cmd = osc_share_replicas.PromoteShareReplica(self.app, None)

    def test_share_replica_promote(self):
        arglist = [
            self.share_replica.id,
        ]
        verifylist = [('replica', self.share_replica.id), ('wait', False)]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        result = self.cmd.take_action(parsed_args)

        self.replicas_mock.promote.assert_called_with(self.share_replica)
        self.assertIsNone(result)

    def test_share_replica_promote_quiesce_wait_time(self):
        wait_time = '5'
        arglist = [self.share_replica.id, '--quiesce-wait-time', wait_time]
        verifylist = [
            ('replica', self.share_replica.id),
            ('quiesce_wait_time', wait_time),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        result = self.cmd.take_action(parsed_args)

        self.replicas_mock.promote.assert_called_with(
            self.share_replica, wait_time
        )
        self.assertIsNone(result)

    @mock.patch.object(
        osc_share_replicas.osc_utils, 'wait_for_status', mock.Mock()
    )
    def test_share_replica_promote_wait(self):
        arglist = [self.share_replica.id, '--wait']
        verifylist = [('replica', self.share_replica.id), ('wait', True)]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        result = self.cmd.take_action(parsed_args)

        self.replicas_mock.promote.assert_called_with(self.share_replica)
        self.assertIsNone(result)
        osc_share_replicas.osc_utils.wait_for_status.assert_called_once_with(
            status_f=self.replicas_mock.get,
            res_id=self.share_replica.id,
            success_status=['active'],
            status_field='replica_state',
        )

    def test_share_replica_promote_exception(self):
        arglist = [
            self.share_replica.id,
        ]
        verifylist = [
            ('replica', self.share_replica.id),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.replicas_mock.promote.side_effect = Exception()

        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )


class TestShareReplicaResync(TestShareReplica):
    def setUp(self):
        super().setUp()

        self.share_replica = manila_fakes.FakeShareReplica.create_one_replica()
        self.replicas_mock.get.return_value = self.share_replica

        self.cmd = osc_share_replicas.ResyncShareReplica(self.app, None)

    def test_share_replica_resync(self):
        arglist = [
            self.share_replica.id,
        ]
        verifylist = [
            ('replica', self.share_replica.id),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        result = self.cmd.take_action(parsed_args)

        self.replicas_mock.resync.assert_called_with(self.share_replica)
        self.assertIsNone(result)

    def test_share_replica_resync_exception(self):
        arglist = [
            self.share_replica.id,
        ]
        verifylist = [
            ('replica', self.share_replica.id),
        ]
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)

        self.replicas_mock.resync.side_effect = Exception()

        self.assertRaises(
            exceptions.CommandError, self.cmd.take_action, parsed_args
        )
