// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.
package com.cloud.storage;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutionException;

import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext;
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
import org.apache.cloudstack.framework.jobs.dao.AsyncJobJoinMapDao;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

import com.cloud.configuration.Resource;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.org.Grouping;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.User;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;

@RunWith(MockitoJUnitRunner.class)
public class VolumeApiServiceImplTest {

    @Spy
    @InjectMocks
    private VolumeApiServiceImpl volumeApiServiceImpl = new VolumeApiServiceImpl();
    @Mock
    private VolumeDao volumeDaoMock;
    @Mock
    private SnapshotManager snapshotManagerMock;
    @Mock
    private VolumeDataStoreDao volumeDataStoreDaoMock;
    @Mock
    private AccountManager accountManagerMock;
    @Mock
    private VolumeService volumeServiceMock;
    @Mock
    private ResourceLimitService resourceLimitServiceMock;
    @Mock
    private VolumeDataFactory volumeDataFactoryMock;

    @Mock
    private UserVmDao userVmDaoMock;
    @Mock
    private PrimaryDataStoreDao primaryDataStoreDaoMock;
    @Mock
    private VMSnapshotDao vmSnapshotDaoMock;
    @Mock
    private AsyncJobManager asyncJobManagerMock;
    @Mock
    private AsyncJobJoinMapDao asyncJobJoinMapDaoMock;
    @Mock
    private UserVmManager userVmManagerMock;
    @Mock
    private VMInstanceDao vMInstanceDaoMock;
    @Mock
    private SnapshotInfo snapshotInfoMock;
    @Mock
    private CreateVolumeCmd createVolumeCmdMock;
    @Mock
    private DataCenterDao dataCenterDaoMock;
    @Mock
    private AccountDao accountDaoMock;
    @Mock
    private HostDao hostdaoMock;

    DetachVolumeCmd detachCmd = new DetachVolumeCmd();
    Class<?> _detachCmdClass = detachCmd.getClass();

    @Mock
    private Account accountMock;
    @Mock
    private VolumeVO volumeVoMock;
    @Mock
    private VolumeDataStoreVO volumeDataStoreVoMock;
    @Mock
    private AsyncCallFuture<VolumeApiResult> asyncCallFutureVolumeapiResultMock;
    @Mock
    private VolumeInfo volumeInfoMock;

    private long accountMockId = 456l;
    private long volumeMockId = 12313l;
    private long vmInstanceMockId = 1123l;
    private long volumeSizeMock = 456789921939l;

    @Before
    public void setup() throws Exception {
        Mockito.doReturn(volumeMockId).when(volumeDataStoreVoMock).getVolumeId();
        Mockito.doReturn(volumeMockId).when(volumeVoMock).getId();
        Mockito.doReturn(accountMockId).when(accountMock).getId();
        Mockito.doReturn(volumeSizeMock).when(volumeVoMock).getSize();
        Mockito.doReturn(Mockito.mock(VolumeApiResult.class)).when(asyncCallFutureVolumeapiResultMock).get();

        // mock caller context
        AccountVO account = new AccountVO("admin", 1L, "networkDomain", Account.ACCOUNT_TYPE_NORMAL, "uuid");
        UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN);
        CallContext.register(user, account);
        // mock async context
        AsyncJobExecutionContext context = new AsyncJobExecutionContext();
        AsyncJobExecutionContext.init(volumeApiServiceImpl._jobMgr, asyncJobJoinMapDaoMock);
        AsyncJobVO job = new AsyncJobVO();
        context.setJob(job);
        AsyncJobExecutionContext.setCurrentExecutionContext(context);

        TransactionLegacy txn = TransactionLegacy.open("runVolumeDaoImplTest");
        try {
            // volume of running vm id=1
            VolumeVO volumeOfRunningVm = new VolumeVO("root", 1L, 1L, 1L, 1L, 1L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
            when(volumeApiServiceImpl._volsDao.findById(1L)).thenReturn(volumeOfRunningVm);

            UserVmVO runningVm = new UserVmVO(1L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false, false, 1L, 1L, 1, 1L, null, "vm", null);
            runningVm.setState(State.Running);
            runningVm.setDataCenterId(1L);
            when(volumeApiServiceImpl._userVmDao.findById(1L)).thenReturn(runningVm);

            // volume of stopped vm id=2
            VolumeVO volumeOfStoppedVm = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
            volumeOfStoppedVm.setPoolId(1L);
            when(volumeApiServiceImpl._volsDao.findById(2L)).thenReturn(volumeOfStoppedVm);

            UserVmVO stoppedVm = new UserVmVO(2L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false, false, 1L, 1L, 1, 1L, null, "vm", null);
            stoppedVm.setState(State.Stopped);
            stoppedVm.setDataCenterId(1L);
            when(volumeApiServiceImpl._userVmDao.findById(2L)).thenReturn(stoppedVm);

            // volume of hyperV vm id=3
            UserVmVO hyperVVm = new UserVmVO(3L, "vm", "vm", 1, HypervisorType.Hyperv, 1L, false, false, 1L, 1L, 1, 1L, null, "vm", null);
            hyperVVm.setState(State.Stopped);
            hyperVVm.setDataCenterId(1L);
            when(volumeApiServiceImpl._userVmDao.findById(3L)).thenReturn(hyperVVm);

            VolumeVO volumeOfStoppeHyperVVm = new VolumeVO("root", 1L, 1L, 1L, 1L, 3L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
            volumeOfStoppeHyperVVm.setPoolId(1L);
            when(volumeApiServiceImpl._volsDao.findById(3L)).thenReturn(volumeOfStoppeHyperVVm);

            StoragePoolVO unmanagedPool = new StoragePoolVO();

            when(volumeApiServiceImpl._storagePoolDao.findById(1L)).thenReturn(unmanagedPool);

            // volume of managed pool id=4
            StoragePoolVO managedPool = new StoragePoolVO();
            managedPool.setManaged(true);
            when(volumeApiServiceImpl._storagePoolDao.findById(2L)).thenReturn(managedPool);
            VolumeVO managedPoolVolume = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
            managedPoolVolume.setPoolId(2L);
            when(volumeApiServiceImpl._volsDao.findById(4L)).thenReturn(managedPoolVolume);

            // non-root non-datadisk volume
            VolumeInfo volumeWithIncorrectVolumeType = Mockito.mock(VolumeInfo.class);
            when(volumeWithIncorrectVolumeType.getId()).thenReturn(5L);
            when(volumeWithIncorrectVolumeType.getVolumeType()).thenReturn(Volume.Type.ISO);
            when(volumeApiServiceImpl.volFactory.getVolume(5L)).thenReturn(volumeWithIncorrectVolumeType);

            // correct root volume
            VolumeInfo correctRootVolume = Mockito.mock(VolumeInfo.class);
            when(correctRootVolume.getId()).thenReturn(6L);
            when(correctRootVolume.getDataCenterId()).thenReturn(1L);
            when(correctRootVolume.getVolumeType()).thenReturn(Volume.Type.ROOT);
            when(correctRootVolume.getInstanceId()).thenReturn(null);
            when(correctRootVolume.getState()).thenReturn(Volume.State.Ready);
            when(correctRootVolume.getTemplateId()).thenReturn(null);
            when(correctRootVolume.getPoolId()).thenReturn(1L);
            when(volumeApiServiceImpl.volFactory.getVolume(6L)).thenReturn(correctRootVolume);

            VolumeVO correctRootVolumeVO = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
            when(volumeApiServiceImpl._volsDao.findById(6L)).thenReturn(correctRootVolumeVO);

            // managed root volume
            VolumeInfo managedVolume = Mockito.mock(VolumeInfo.class);
            when(managedVolume.getId()).thenReturn(7L);
            when(managedVolume.getDataCenterId()).thenReturn(1L);
            when(managedVolume.getVolumeType()).thenReturn(Volume.Type.ROOT);
            when(managedVolume.getInstanceId()).thenReturn(null);
            when(managedVolume.getPoolId()).thenReturn(2L);
            when(volumeApiServiceImpl.volFactory.getVolume(7L)).thenReturn(managedVolume);

            VolumeVO managedVolume1 = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
            managedVolume1.setPoolId(2L);
            managedVolume1.setDataCenterId(1L);
            when(volumeApiServiceImpl._volsDao.findById(7L)).thenReturn(managedVolume1);

            // vm having root volume
            UserVmVO vmHavingRootVolume = new UserVmVO(4L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false, false, 1L, 1L, 1, 1L, null, "vm", null);
            vmHavingRootVolume.setState(State.Stopped);
            vmHavingRootVolume.setDataCenterId(1L);
            when(volumeApiServiceImpl._userVmDao.findById(4L)).thenReturn(vmHavingRootVolume);
            List<VolumeVO> vols = new ArrayList<VolumeVO>();
            vols.add(new VolumeVO());
            when(volumeApiServiceImpl._volsDao.findByInstanceAndDeviceId(4L, 0L)).thenReturn(vols);

            // volume in uploaded state
            VolumeInfo uploadedVolume = Mockito.mock(VolumeInfo.class);
            when(uploadedVolume.getId()).thenReturn(8L);
            when(uploadedVolume.getDataCenterId()).thenReturn(1L);
            when(uploadedVolume.getVolumeType()).thenReturn(Volume.Type.ROOT);
            when(uploadedVolume.getInstanceId()).thenReturn(null);
            when(uploadedVolume.getPoolId()).thenReturn(1L);
            when(uploadedVolume.getState()).thenReturn(Volume.State.Uploaded);
            when(volumeApiServiceImpl.volFactory.getVolume(8L)).thenReturn(uploadedVolume);

            VolumeVO upVolume = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
            upVolume.setPoolId(1L);
            upVolume.setDataCenterId(1L);
            upVolume.setState(Volume.State.Uploaded);
            when(volumeApiServiceImpl._volsDao.findById(8L)).thenReturn(upVolume);

            // helper dao methods mock
            when(volumeApiServiceImpl._vmSnapshotDao.findByVm(any(Long.class))).thenReturn(new ArrayList<VMSnapshotVO>());
            when(volumeApiServiceImpl._vmInstanceDao.findById(any(Long.class))).thenReturn(stoppedVm);

            DataCenterVO enabledZone = Mockito.mock(DataCenterVO.class);
            when(enabledZone.getAllocationState()).thenReturn(Grouping.AllocationState.Enabled);

            when(volumeApiServiceImpl._dcDao.findById(anyLong())).thenReturn(enabledZone);

        } finally {
            txn.close("runVolumeDaoImplTest");
        }

        // helper methods mock
        doNothing().when(volumeApiServiceImpl._accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class));
        doNothing().when(volumeApiServiceImpl._jobMgr).updateAsyncJobAttachment(any(Long.class), any(String.class), any(Long.class));
        when(volumeApiServiceImpl._jobMgr.submitAsyncJob(any(AsyncJobVO.class), any(String.class), any(Long.class))).thenReturn(1L);
    }

    /**
     * TESTS FOR DETACH ROOT VOLUME, COUNT=4
     * @throws Exception
     */

    @Test(expected = InvalidParameterValueException.class)
    public void testDetachVolumeFromRunningVm() throws NoSuchFieldException, IllegalAccessException {
        Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
        dedicateIdField.setAccessible(true);
        dedicateIdField.set(detachCmd, 1L);
        volumeApiServiceImpl.detachVolumeFromVM(detachCmd);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testDetachVolumeFromStoppedHyperVVm() throws NoSuchFieldException, IllegalAccessException {
        Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
        dedicateIdField.setAccessible(true);
        dedicateIdField.set(detachCmd, 3L);
        volumeApiServiceImpl.detachVolumeFromVM(detachCmd);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testDetachVolumeOfManagedDataStore() throws NoSuchFieldException, IllegalAccessException {
        Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
        dedicateIdField.setAccessible(true);
        dedicateIdField.set(detachCmd, 4L);
        volumeApiServiceImpl.detachVolumeFromVM(detachCmd);
    }

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void testDetachVolumeFromStoppedXenVm() throws NoSuchFieldException, IllegalAccessException {
        thrown.expect(NullPointerException.class);
        Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
        dedicateIdField.setAccessible(true);
        dedicateIdField.set(detachCmd, 2L);
        volumeApiServiceImpl.detachVolumeFromVM(detachCmd);
    }

    /**
     * TESTS FOR ATTACH ROOT VOLUME, COUNT=7
     */

    // Negative test - try to attach non-root non-datadisk volume
    @Test(expected = InvalidParameterValueException.class)
    public void attachIncorrectDiskType() throws NoSuchFieldException, IllegalAccessException {
        volumeApiServiceImpl.attachVolumeToVM(1L, 5L, 0L);
    }

    // Negative test - attach root volume to running vm
    @Test(expected = InvalidParameterValueException.class)
    public void attachRootDiskToRunningVm() throws NoSuchFieldException, IllegalAccessException {
        volumeApiServiceImpl.attachVolumeToVM(1L, 6L, 0L);
    }

    // Negative test - attach root volume to non-xen vm
    @Test(expected = InvalidParameterValueException.class)
    public void attachRootDiskToHyperVm() throws NoSuchFieldException, IllegalAccessException {
        volumeApiServiceImpl.attachVolumeToVM(3L, 6L, 0L);
    }

    // Negative test - attach root volume from the managed data store
    @Test(expected = InvalidParameterValueException.class)
    public void attachRootDiskOfManagedDataStore() throws NoSuchFieldException, IllegalAccessException {
        volumeApiServiceImpl.attachVolumeToVM(2L, 7L, 0L);
    }

    // Negative test - root volume can't be attached to the vm already having a root volume attached
    @Test(expected = InvalidParameterValueException.class)
    public void attachRootDiskToVmHavingRootDisk() throws NoSuchFieldException, IllegalAccessException {
        volumeApiServiceImpl.attachVolumeToVM(4L, 6L, 0L);
    }

    // Negative test - root volume in uploaded state can't be attached
    @Test(expected = InvalidParameterValueException.class)
    public void attachRootInUploadedState() throws NoSuchFieldException, IllegalAccessException {
        volumeApiServiceImpl.attachVolumeToVM(2L, 8L, 0L);
    }

    // Positive test - attach ROOT volume in correct state, to the vm not having root volume attached
    @Test
    public void attachRootVolumePositive() throws NoSuchFieldException, IllegalAccessException {
        thrown.expect(NullPointerException.class);
        volumeApiServiceImpl.attachVolumeToVM(2L, 6L, 0L);
    }

    // volume not Ready
    @Test(expected = InvalidParameterValueException.class)
    public void testTakeSnapshotF1() throws ResourceAllocationException {
        when(volumeDataFactoryMock.getVolume(anyLong())).thenReturn(volumeInfoMock);
        when(volumeInfoMock.getState()).thenReturn(Volume.State.Allocated);
        when(volumeInfoMock.getPoolId()).thenReturn(1L);
        volumeApiServiceImpl.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false);
    }

    @Test
    public void testTakeSnapshotF2() throws ResourceAllocationException {
        when(volumeDataFactoryMock.getVolume(anyLong())).thenReturn(volumeInfoMock);
        when(volumeInfoMock.getState()).thenReturn(Volume.State.Ready);
        when(volumeInfoMock.getInstanceId()).thenReturn(null);
        when(volumeInfoMock.getPoolId()).thenReturn(1L);
        when(volumeServiceMock.takeSnapshot(Mockito.any(VolumeInfo.class))).thenReturn(snapshotInfoMock);
        volumeApiServiceImpl.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false);
    }

    @Test
    public void testNullGetVolumeNameFromCmd() {
        when(createVolumeCmdMock.getVolumeName()).thenReturn(null);
        Assert.assertNotNull(volumeApiServiceImpl.getVolumeNameFromCommand(createVolumeCmdMock));
    }

    @Test
    public void testEmptyGetVolumeNameFromCmd() {
        when(createVolumeCmdMock.getVolumeName()).thenReturn("");
        Assert.assertNotNull(volumeApiServiceImpl.getVolumeNameFromCommand(createVolumeCmdMock));
    }

    @Test
    public void testBlankGetVolumeNameFromCmd() {
        when(createVolumeCmdMock.getVolumeName()).thenReturn("   ");
        Assert.assertNotNull(volumeApiServiceImpl.getVolumeNameFromCommand(createVolumeCmdMock));
    }

    @Test
    public void testNonEmptyGetVolumeNameFromCmd() {
        when(createVolumeCmdMock.getVolumeName()).thenReturn("abc");
        Assert.assertSame(volumeApiServiceImpl.getVolumeNameFromCommand(createVolumeCmdMock), "abc");
    }

    @Test
    public void testUpdateMissingRootDiskControllerWithNullChainInfo() {
        volumeApiServiceImpl.updateMissingRootDiskController(null, null);
        verify(userVmManagerMock, times(0)).persistDeviceBusInfo(any(UserVmVO.class), anyString());
    }

    @Test
    public void testUpdateMissingRootDiskControllerWithValidChainInfo() {
        UserVmVO vm = userVmDaoMock.findById(1L);
        assert vm.getType() == VirtualMachine.Type.User;
        volumeApiServiceImpl.updateMissingRootDiskController(vm, "{\"diskDeviceBusName\":\"scsi0:0\",\"diskChain\":[\"[somedatastore] i-3-VM-somePath/ROOT-1.vmdk\"]}");
        verify(userVmManagerMock, times(1)).persistDeviceBusInfo(any(UserVmVO.class), eq("scsi"));
    }

    @Test
    /**
     * Setting locationType for a non-managed storage should give an error
     */
    public void testAllocSnapshotNonManagedStorageArchive() {
        try {
            volumeApiServiceImpl.allocSnapshot(6L, 1L, "test", Snapshot.LocationType.SECONDARY);
        } catch (InvalidParameterValueException e) {
            Assert.assertEquals(e.getMessage(), "VolumeId: 6 LocationType is supported only for managed storage");
            return;
        } catch (ResourceAllocationException e) {
            Assert.fail("Unexpected excepiton " + e.getMessage());
        }

        Assert.fail("Expected Exception for archive in non-managed storage");
    }

    /**
     * The resource limit check for primary storage should not be skipped for Volume in 'Uploaded' state.
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     * @throws ResourceAllocationException
     */
    @Test
    public void testResourceLimitCheckForUploadedVolume() throws NoSuchFieldException, IllegalAccessException, ResourceAllocationException {
        doThrow(new ResourceAllocationException("primary storage resource limit check failed", Resource.ResourceType.primary_storage)).when(volumeApiServiceImpl._resourceLimitMgr)
        .checkResourceLimit(any(AccountVO.class), any(Resource.ResourceType.class), any(Long.class));
        UserVmVO vm = Mockito.mock(UserVmVO.class);
        VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
        when(volumeToAttach.getId()).thenReturn(9L);
        when(volumeToAttach.getDataCenterId()).thenReturn(34L);
        when(volumeToAttach.getVolumeType()).thenReturn(Volume.Type.DATADISK);
        when(volumeToAttach.getInstanceId()).thenReturn(null);
        when(userVmDaoMock.findById(anyLong())).thenReturn(vm);
        when(vm.getType()).thenReturn(VirtualMachine.Type.User);
        when(vm.getState()).thenReturn(State.Running);
        when(vm.getDataCenterId()).thenReturn(34L);
        when(volumeApiServiceImpl._volsDao.findByInstanceAndType(anyLong(), any(Volume.Type.class))).thenReturn(new ArrayList<>(10));
        when(volumeApiServiceImpl.volFactory.getVolume(9L)).thenReturn(volumeToAttach);
        when(volumeToAttach.getState()).thenReturn(Volume.State.Uploaded);
        DataCenterVO zoneWithDisabledLocalStorage = Mockito.mock(DataCenterVO.class);
        when(volumeApiServiceImpl._dcDao.findById(anyLong())).thenReturn(zoneWithDisabledLocalStorage);
        when(zoneWithDisabledLocalStorage.isLocalStorageEnabled()).thenReturn(true);
        try {
            volumeApiServiceImpl.attachVolumeToVM(2L, 9L, null);
        } catch (InvalidParameterValueException e) {
            Assert.assertEquals(e.getMessage(), ("primary storage resource limit check failed"));
        }
    }

    @After
    public void tearDown() {
        CallContext.unregister();
    }

    @Test(expected = InvalidParameterValueException.class)
    public void retrieveAndValidateVolumeTestVolumeNotFound() {
        Mockito.doReturn(null).when(volumeDaoMock).findById(volumeMockId);
        volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void retrieveAndValidateVolumeTestCannotOperateOnVolumeDueToSnapshot() {
        Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
        Mockito.doReturn(false).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);

        volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void retrieveAndValidateVolumeTestVolumePluggedIntoVm() {
        Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
        Mockito.doReturn(vmInstanceMockId).when(volumeVoMock).getInstanceId();

        Mockito.doReturn(true).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);

        volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void retrieveAndValidateVolumeTestStateUploadOpAndDownloadInProgress() {
        Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
        Mockito.doReturn(null).when(volumeVoMock).getInstanceId();
        Mockito.doReturn(Volume.State.UploadOp).when(volumeVoMock).getState();

        Mockito.doReturn(true).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);
        Mockito.doReturn(volumeDataStoreVoMock).when(volumeDataStoreDaoMock).findByVolume(volumeMockId);
        Mockito.doReturn(VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS).when(volumeDataStoreVoMock).getDownloadState();

        volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void retrieveAndValidateVolumeTestStateNotUploaded() {
        Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
        Mockito.doReturn(null).when(volumeVoMock).getInstanceId();
        Mockito.doReturn(Volume.State.NotUploaded).when(volumeVoMock).getState();

        Mockito.doReturn(true).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);

        volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void retrieveAndValidateVolumeTestUploadInProgress() {
        Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
        Mockito.doReturn(null).when(volumeVoMock).getInstanceId();
        Mockito.doReturn(Volume.State.UploadInProgress).when(volumeVoMock).getState();

        Mockito.doReturn(true).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);

        volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
    }

    @Test
    public void retrieveAndValidateVolumeTest() {
        Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
        Mockito.doReturn(null).when(volumeVoMock).getInstanceId();
        Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();

        Mockito.doReturn(true).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);
        Mockito.doNothing().when(accountManagerMock).checkAccess(accountMock, null, true, volumeVoMock);
        volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);

        Mockito.verify(accountManagerMock).checkAccess(accountMock, null, true, volumeVoMock);
    }

    @Test
    public void destroyVolumeIfPossibleTestVolumeStateIsDestroy() {
        Mockito.doReturn(Volume.State.Destroy).when(volumeVoMock).getState();
        configureMocksForTestDestroyVolumeWhenVolume();

        volumeApiServiceImpl.destroyVolumeIfPossible(volumeVoMock);

        verifyMocksForTestDestroyVolumeWhenVolumeIsNotInRightState();
    }

    @Test
    public void destroyVolumeIfPossibleTestVolumeStateIsExpunging() {
        Mockito.doReturn(Volume.State.Expunging).when(volumeVoMock).getState();
        configureMocksForTestDestroyVolumeWhenVolume();

        volumeApiServiceImpl.destroyVolumeIfPossible(volumeVoMock);

        verifyMocksForTestDestroyVolumeWhenVolumeIsNotInRightState();
    }

    @Test
    public void destroyVolumeIfPossibleTestVolumeStateIsExpunged() {
        Mockito.doReturn(Volume.State.Expunged).when(volumeVoMock).getState();
        configureMocksForTestDestroyVolumeWhenVolume();

        volumeApiServiceImpl.destroyVolumeIfPossible(volumeVoMock);

        verifyMocksForTestDestroyVolumeWhenVolumeIsNotInRightState();
    }

    @Test
    public void destroyVolumeIfPossibleTestVolumeStateReady() {
        Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();
        configureMocksForTestDestroyVolumeWhenVolume();

        volumeApiServiceImpl.destroyVolumeIfPossible(volumeVoMock);

        Mockito.verify(volumeServiceMock, Mockito.times(1)).destroyVolume(volumeMockId);
        Mockito.verify(resourceLimitServiceMock, Mockito.times(1)).decrementResourceCount(accountMockId, ResourceType.volume, true);
        Mockito.verify(resourceLimitServiceMock, Mockito.times(1)).decrementResourceCount(accountMockId, ResourceType.primary_storage, true, volumeSizeMock);
    }

    private void verifyMocksForTestDestroyVolumeWhenVolumeIsNotInRightState() {
        Mockito.verify(volumeServiceMock, Mockito.times(0)).destroyVolume(volumeMockId);
        Mockito.verify(resourceLimitServiceMock, Mockito.times(0)).decrementResourceCount(accountMockId, ResourceType.volume, true);
        Mockito.verify(resourceLimitServiceMock, Mockito.times(0)).decrementResourceCount(accountMockId, ResourceType.primary_storage, true, volumeSizeMock);
    }

    private void configureMocksForTestDestroyVolumeWhenVolume() {
        Mockito.doReturn(accountMockId).when(volumeVoMock).getAccountId();
        Mockito.doReturn(true).when(volumeVoMock).isDisplayVolume();

        Mockito.doNothing().when(volumeServiceMock).destroyVolume(volumeMockId);
        Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.volume, true);
        Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.primary_storage, true, volumeSizeMock);
    }

    @Test
    public void expungeVolumesInPrimaryStorageIfNeededTestVolumeNotInPrimaryDataStore() throws InterruptedException, ExecutionException {
        Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
        Mockito.doReturn(null).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary);

        volumeApiServiceImpl.expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);

        Mockito.verify(volumeServiceMock, Mockito.times(0)).expungeVolumeAsync(volumeInfoMock);
        Mockito.verify(asyncCallFutureVolumeapiResultMock, Mockito.times(0)).get();
    }

    @Test
    public void expungeVolumesInPrimaryStorageIfNeededTestVolumeInPrimaryDataStore() throws InterruptedException, ExecutionException {
        Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
        Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary);

        volumeApiServiceImpl.expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);

        Mockito.verify(volumeServiceMock, Mockito.times(1)).expungeVolumeAsync(volumeInfoMock);
        Mockito.verify(asyncCallFutureVolumeapiResultMock, Mockito.times(1)).get();
    }

    @Test(expected = InterruptedException.class)
    public void expungeVolumesInPrimaryStorageIfNeededTestThrowingInterruptedException() throws InterruptedException, ExecutionException {
        Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
        Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary);
        Mockito.doThrow(InterruptedException.class).when(asyncCallFutureVolumeapiResultMock).get();

        volumeApiServiceImpl.expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
    }

    @Test(expected = ExecutionException.class)
    public void expungeVolumesInPrimaryStorageIfNeededTestThrowingExecutionException() throws InterruptedException, ExecutionException {
        Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
        Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary);
        Mockito.doThrow(ExecutionException.class).when(asyncCallFutureVolumeapiResultMock).get();

        volumeApiServiceImpl.expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
    }

    @Test
    public void expungeVolumesInSecondaryStorageIfNeededTestVolumeNotFoundInSecondaryStorage() throws InterruptedException, ExecutionException {
        Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
        Mockito.doReturn(null).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image);
        Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
        Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId();
        Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize();

        volumeApiServiceImpl.expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);

        Mockito.verify(volumeServiceMock, Mockito.times(0)).expungeVolumeAsync(volumeInfoMock);
        Mockito.verify(asyncCallFutureVolumeapiResultMock, Mockito.times(0)).get();
        Mockito.verify(resourceLimitServiceMock, Mockito.times(0)).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
    }

    @Test
    public void expungeVolumesInSecondaryStorageIfNeededTestVolumeFoundInSecondaryStorage() throws InterruptedException, ExecutionException {
        Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
        Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image);
        Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
        Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId();
        Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize();

        volumeApiServiceImpl.expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);

        Mockito.verify(volumeServiceMock, Mockito.times(1)).expungeVolumeAsync(volumeInfoMock);
        Mockito.verify(asyncCallFutureVolumeapiResultMock, Mockito.times(1)).get();
        Mockito.verify(resourceLimitServiceMock, Mockito.times(1)).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
    }

    @Test(expected = InterruptedException.class)
    public void expungeVolumesInSecondaryStorageIfNeededTestthrowinInterruptedException() throws InterruptedException, ExecutionException {
        Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
        Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image);
        Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
        Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId();
        Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize();

        Mockito.doThrow(InterruptedException.class).when(asyncCallFutureVolumeapiResultMock).get();

        volumeApiServiceImpl.expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);

    }

    @Test(expected = ExecutionException.class)
    public void expungeVolumesInSecondaryStorageIfNeededTestthrowinExecutionException() throws InterruptedException, ExecutionException {
        Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
        Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image);
        Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
        Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId();
        Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize();

        Mockito.doThrow(ExecutionException.class).when(asyncCallFutureVolumeapiResultMock).get();

        volumeApiServiceImpl.expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);

    }

    @Test
    public void cleanVolumesCacheTest() {
        List<VolumeInfo> volumeInfos = new ArrayList<>();
        VolumeInfo volumeInfoMock1 = Mockito.mock(VolumeInfo.class);
        VolumeInfo volumeInfoMock2 = Mockito.mock(VolumeInfo.class);

        DataStore dataStoreMock1 = Mockito.mock(DataStore.class);
        DataStore dataStoreMock2 = Mockito.mock(DataStore.class);
        Mockito.doReturn(dataStoreMock1).when(volumeInfoMock1).getDataStore();
        Mockito.doReturn(dataStoreMock2).when(volumeInfoMock2).getDataStore();

        volumeInfos.add(volumeInfoMock1);
        volumeInfos.add(volumeInfoMock2);

        Mockito.doReturn(volumeInfos).when(volumeDataFactoryMock).listVolumeOnCache(volumeMockId);

        volumeApiServiceImpl.cleanVolumesCache(volumeVoMock);

        Mockito.verify(dataStoreMock1).getName();
        Mockito.verify(dataStoreMock2).getName();

        Mockito.verify(volumeInfoMock1).delete();
        Mockito.verify(volumeInfoMock2).delete();
    }

    @Test
    public void deleteVolumeTestVolumeStateAllocated() throws InterruptedException, ExecutionException, NoTransitionException {
        Mockito.doReturn(Volume.State.Allocated).when(volumeVoMock).getState();

        Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
        Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
        Mockito.doNothing().when(volumeApiServiceImpl).cleanVolumesCache(volumeVoMock);

        Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
        Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);

        boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);

        assertTrue(result);
        Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.verify(volumeDaoMock).remove(volumeMockId);
        Mockito.verify(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);

        Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
        Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
        Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).cleanVolumesCache(volumeVoMock);
    }

    @Test
    public void deleteVolumeTestVolumeStateReady() throws InterruptedException, ExecutionException, NoTransitionException {
        Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();

        Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
        Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
        Mockito.doNothing().when(volumeApiServiceImpl).cleanVolumesCache(volumeVoMock);

        Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
        Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);

        boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);

        assertTrue(result);
        Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.verify(volumeDaoMock, Mockito.times(0)).remove(volumeMockId);
        Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);

        Mockito.verify(volumeApiServiceImpl, Mockito.times(1)).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
        Mockito.verify(volumeApiServiceImpl, Mockito.times(1)).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
        Mockito.verify(volumeApiServiceImpl, Mockito.times(1)).cleanVolumesCache(volumeVoMock);
    }

    @Test
    public void deleteVolumeTestVolumeStateReadyThrowingInterruptedException() throws InterruptedException, ExecutionException, NoTransitionException {
        Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();

        Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.doThrow(InterruptedException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);

        Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
        Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);

        boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);

        assertFalse(result);
        Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.verify(volumeDaoMock, Mockito.times(0)).remove(volumeMockId);
        Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
    }

    @Test
    public void deleteVolumeTestVolumeStateReadyThrowingExecutionException() throws InterruptedException, ExecutionException, NoTransitionException {
        Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();

        Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.doThrow(ExecutionException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);

        Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
        Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);

        boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);

        assertFalse(result);
        Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.verify(volumeDaoMock, Mockito.times(0)).remove(volumeMockId);
        Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
    }

    @Test
    public void deleteVolumeTestVolumeStateReadyThrowingNoTransitionException() throws InterruptedException, ExecutionException, NoTransitionException {
        Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();

        Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.doThrow(NoTransitionException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);

        Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
        Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);

        boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);

        assertFalse(result);
        Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.verify(volumeDaoMock, Mockito.times(0)).remove(volumeMockId);
        Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
    }

    @Test(expected = RuntimeException.class)
    public void deleteVolumeTestVolumeStateReadyThrowingRuntimeException() throws InterruptedException, ExecutionException, NoTransitionException {
        Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();

        Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
        Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
        Mockito.doThrow(RuntimeException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);

        Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
        Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);

        volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);
    }
}
