content: //
  // 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 org.apache.cloudstack.storage.datastore.driver;
  
  import com.cloud.agent.api.Answer;
  import com.cloud.agent.api.GetVolumeStatAnswer;
  import com.cloud.agent.api.GetVolumeStatCommand;
  import com.cloud.agent.api.storage.MigrateVolumeAnswer;
  import com.cloud.agent.api.storage.MigrateVolumeCommand;
  import com.cloud.agent.api.to.DataTO;
  import com.cloud.agent.api.to.DiskTO;
  import com.cloud.configuration.Config;
  import com.cloud.host.Host;
  import com.cloud.host.HostVO;
  import com.cloud.host.dao.HostDao;
  import com.cloud.storage.Storage;
  import com.cloud.storage.Volume;
  import com.cloud.storage.VolumeVO;
  import com.cloud.storage.dao.VolumeDao;
  import com.cloud.storage.dao.VolumeDetailsDao;
  import com.cloud.utils.exception.CloudRuntimeException;
  import com.cloud.vm.VMInstanceVO;
  import com.cloud.vm.VirtualMachine;
  import com.cloud.vm.dao.VMInstanceDao;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
  import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
  import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
  import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
  import org.apache.cloudstack.storage.RemoteHostEndPoint;
  import org.apache.cloudstack.storage.command.CreateObjectAnswer;
  import org.apache.cloudstack.storage.datastore.client.ScaleIOGatewayClient;
  import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
  import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
  import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
  import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
  import org.apache.cloudstack.storage.to.VolumeObjectTO;
  import org.junit.After;
  import org.junit.AfterClass;
  import org.junit.Assert;
  import org.junit.Before;
  import org.junit.BeforeClass;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.mockito.InjectMocks;
  import org.mockito.Mock;
  import org.mockito.MockedStatic;
  import org.mockito.Mockito;
  import org.mockito.MockitoAnnotations;
  import org.mockito.Spy;
  import org.mockito.junit.MockitoJUnitRunner;
  
  import java.util.Optional;
  
  import static org.mockito.ArgumentMatchers.any;
  import static org.mockito.Mockito.doNothing;
  import static org.mockito.Mockito.doReturn;
  import static org.mockito.Mockito.mockStatic;
  import static org.mockito.Mockito.when;
  
  @RunWith(MockitoJUnitRunner.class)
  public class ScaleIOPrimaryDataStoreDriverTest {
  
      @Spy
      @InjectMocks
      ScaleIOPrimaryDataStoreDriver scaleIOPrimaryDataStoreDriver = new ScaleIOPrimaryDataStoreDriver();
      @Mock
      StoragePoolDetailsDao storagePoolDetailsDao;
      @Mock
      PrimaryDataStoreDao storagePoolDao;
      @Mock
      VolumeDao volumeDao;
      @Mock
      VolumeDetailsDao volumeDetailsDao;
      @Mock
      VolumeService volumeService;
      @Mock
      VMInstanceDao vmInstanceDao;
      @Mock
      HostDao hostDao;
      @Mock
      ConfigurationDao configDao;
  
      static MockedStatic<RemoteHostEndPoint> remoteHostEndPointMock;
  
      private AutoCloseable closeable;
  
      @BeforeClass
      public static void init() {
          remoteHostEndPointMock = mockStatic(RemoteHostEndPoint.class);
      }
  
      @AfterClass
      public static void close() {
          remoteHostEndPointMock.close();
      }
  
      @Before
      public void initMocks() {
          closeable = MockitoAnnotations.openMocks(this);
      }
  
      @After
      public void tearDown() throws Exception {
          closeable.close();
      }
  
      @Test
      public void testSameScaleIOStorageInstance() {
          DataStore srcStore = Mockito.mock(DataStore.class);
          DataStore destStore = Mockito.mock(DataStore.class);
          when(srcStore.getId()).thenReturn(1L);
          when(destStore.getId()).thenReturn(2L);
  
          StoragePoolDetailVO srcPoolSystemIdDetail = Mockito.mock(StoragePoolDetailVO.class);
          String srcPoolSystemId = "610204d03e3ad60f";
          when(srcPoolSystemIdDetail.getValue()).thenReturn(srcPoolSystemId);
  
          StoragePoolDetailVO destPoolSystemIdDetail = Mockito.mock(StoragePoolDetailVO.class);
          String destPoolSystemId = "610204d03e3ad60f";
          when(destPoolSystemIdDetail.getValue()).thenReturn(destPoolSystemId);
  
          when(storagePoolDetailsDao.findDetail(1L,ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID)).thenReturn(srcPoolSystemIdDetail);
          when(storagePoolDetailsDao.findDetail(2L,ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID)).thenReturn(destPoolSystemIdDetail);
  
          boolean result = scaleIOPrimaryDataStoreDriver.isSameScaleIOStorageInstance(srcStore, destStore);
  
          Assert.assertTrue(result);
      }
  
      @Test
      public void testDifferentScaleIOStorageInstance() {
          DataStore srcStore = Mockito.mock(DataStore.class);
          DataStore destStore = Mockito.mock(DataStore.class);
          when(srcStore.getId()).thenReturn(1L);
          when(destStore.getId()).thenReturn(2L);
  
          StoragePoolDetailVO srcPoolSystemIdDetail = Mockito.mock(StoragePoolDetailVO.class);
          String srcPoolSystemId = "610204d03e3ad60f";
          when(srcPoolSystemIdDetail.getValue()).thenReturn(srcPoolSystemId);
  
          StoragePoolDetailVO destPoolSystemIdDetail = Mockito.mock(StoragePoolDetailVO.class);
          String destPoolSystemId = "7332760565f6340f";
          when(destPoolSystemIdDetail.getValue()).thenReturn(destPoolSystemId);
  
          when(storagePoolDetailsDao.findDetail(1L,ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID)).thenReturn(srcPoolSystemIdDetail);
          when(storagePoolDetailsDao.findDetail(2L,ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID)).thenReturn(destPoolSystemIdDetail);
  
          boolean result = scaleIOPrimaryDataStoreDriver.isSameScaleIOStorageInstance(srcStore, destStore);
  
          Assert.assertFalse(result);
      }
  
      @Test (expected = CloudRuntimeException.class)
      public void testCheckVolumeOnDifferentScaleIOStorageInstanceSystemIdShouldNotBeNull() {
          DataStore srcStore = Mockito.mock(DataStore.class);
          DataStore destStore = Mockito.mock(DataStore.class);
          when(srcStore.getId()).thenReturn(1L);
          when(destStore.getId()).thenReturn(2L);
  
          StoragePoolDetailVO srcPoolSystemIdDetail = Mockito.mock(StoragePoolDetailVO.class);
          String srcPoolSystemId = "610204d03e3ad60f";
          when(srcPoolSystemIdDetail.getValue()).thenReturn(srcPoolSystemId);
  
          StoragePoolDetailVO destPoolSystemIdDetail = Mockito.mock(StoragePoolDetailVO.class);
          when(destPoolSystemIdDetail.getValue()).thenReturn(null);
  
          when(storagePoolDetailsDao.findDetail(1L,ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID)).thenReturn(srcPoolSystemIdDetail);
          when(storagePoolDetailsDao.findDetail(2L,ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID)).thenReturn(destPoolSystemIdDetail);
  
          scaleIOPrimaryDataStoreDriver.isSameScaleIOStorageInstance(srcStore, destStore);
      }
  
      @Test
      public void testMigrateVolumeWithinSameScaleIOClusterSuccess() throws Exception {
          VolumeInfo srcData = Mockito.mock(VolumeInfo.class);
          VolumeInfo destData = Mockito.mock(VolumeInfo.class);
  
          DataStore srcStore = Mockito.mock(DataStore.class);
          DataStore destStore = Mockito.mock(DataStore.class);
  
          when(srcData.getDataStore()).thenReturn(srcStore);
          when(destData.getDataStore()).thenReturn(destStore);
  
          fillSrcVolumeDetails(srcData, srcStore);
          fillDestVolumeDetails(destData, destStore);
  
          VolumeObjectTO destVolTO = Mockito.mock(VolumeObjectTO.class);
          when(destData.getTO()).thenReturn(destVolTO);
          Host host = prepareEndpointForVolumeOperation(srcData);
          RemoteHostEndPoint ep = Mockito.mock(RemoteHostEndPoint.class);
          remoteHostEndPointMock.when(() -> RemoteHostEndPoint.getHypervisorHostEndPoint(host)).thenReturn(ep);
  
          long volumeVirtualSize = 68673077248L;
          DataTO dataTO = Mockito.mock(DataTO.class);
          CreateObjectAnswer createAnswer = new CreateObjectAnswer(dataTO);
          doReturn(createAnswer).when(scaleIOPrimaryDataStoreDriver).createVolume(destData, 2L, true, volumeVirtualSize);
          when(dataTO.getPath()).thenReturn("bec0ba7700000007:vol-11-6aef-10ee");
          doReturn(true).when(scaleIOPrimaryDataStoreDriver)
                  .grantAccess(any(), any(), any());
  
          when(configDao.getValue(Config.MigrateWait.key())).thenReturn("3600");
  
          GetVolumeStatAnswer getVolumeStatAnswer = Mockito.mock(GetVolumeStatAnswer.class);
          when(ep.sendMessage(any(GetVolumeStatCommand.class))).thenReturn(getVolumeStatAnswer);
          when(getVolumeStatAnswer.getResult()).thenReturn(true);
          when(getVolumeStatAnswer.getVirtualSize()).thenReturn(volumeVirtualSize);
  
          MigrateVolumeAnswer migrateVolumeAnswer = Mockito.mock(MigrateVolumeAnswer.class);
          when(ep.sendMessage(any(MigrateVolumeCommand.class))).thenReturn(migrateVolumeAnswer);
          when(migrateVolumeAnswer.getResult()).thenReturn(true);
  
          Mockito.doNothing().when(scaleIOPrimaryDataStoreDriver)
                  .updateVolumeAfterCopyVolume(any(), any());
          Mockito.doNothing().when(scaleIOPrimaryDataStoreDriver)
                  .updateSnapshotsAfterCopyVolume(any(), any());
          Mockito.doNothing().when(scaleIOPrimaryDataStoreDriver)
                  .deleteSourceVolumeAfterSuccessfulBlockCopy(any(), any());
  
          Answer answer = scaleIOPrimaryDataStoreDriver.liveMigrateVolume(srcData, destData);
  
          Assert.assertTrue(answer.getResult());
      }
  
      @Test
      public void testMigrateVolumeWithinSameScaleIOClusterFailure() throws Exception {
          VolumeInfo srcData = Mockito.mock(VolumeInfo.class);
          VolumeInfo destData = Mockito.mock(VolumeInfo.class);
  
          DataStore srcStore = Mockito.mock(DataStore.class);
          DataStore destStore = Mockito.mock(DataStore.class);
  
          when(srcData.getDataStore()).thenReturn(srcStore);
          when(destData.getDataStore()).thenReturn(destStore);
  
          fillSrcVolumeDetails(srcData, srcStore);
          fillDestVolumeDetails(destData, destStore);
  
          VolumeObjectTO destVolTO = Mockito.mock(VolumeObjectTO.class);
          when(destData.getTO()).thenReturn(destVolTO);
          Host host = prepareEndpointForVolumeOperation(srcData);
          RemoteHostEndPoint ep = Mockito.mock(RemoteHostEndPoint.class);
          remoteHostEndPointMock.when(() -> RemoteHostEndPoint.getHypervisorHostEndPoint(host)).thenReturn(ep);
  
          DataTO dataTO = Mockito.mock(DataTO.class);
          CreateObjectAnswer createAnswer = new CreateObjectAnswer(dataTO);
          Mockito.lenient().doReturn(createAnswer).when(scaleIOPrimaryDataStoreDriver).createVolume(destData, 2L, true, null);
          Mockito.lenient().when(dataTO.getPath()).thenReturn("bec0ba7700000007:vol-11-6aef-10ee");
          Mockito.lenient().doReturn(true).when(scaleIOPrimaryDataStoreDriver)
                  .grantAccess(any(), any(), any());
  
          Mockito.lenient().when(configDao.getValue(Config.MigrateWait.key())).thenReturn("3600");
  
          GetVolumeStatAnswer getVolumeStatAnswer = Mockito.mock(GetVolumeStatAnswer.class);
          Mockito.lenient().when(ep.sendMessage(any(GetVolumeStatCommand.class))).thenReturn(getVolumeStatAnswer);
          Mockito.lenient().when(getVolumeStatAnswer.getResult()).thenReturn(false);
  
          MigrateVolumeAnswer migrateVolumeAnswer = Mockito.mock(MigrateVolumeAnswer.class);
          when(ep.sendMessage(any())).thenReturn(migrateVolumeAnswer);
          Mockito.lenient().when(migrateVolumeAnswer.getResult()).thenReturn(false);
          Mockito.lenient().doNothing().when(scaleIOPrimaryDataStoreDriver)
                  .revertBlockCopyVolumeOperations(any(), any(), any(), any());
  
          Answer answer = scaleIOPrimaryDataStoreDriver.liveMigrateVolume(srcData, destData);
  
          Assert.assertFalse(answer.getResult());
      }
  
      private void fillSrcVolumeDetails(VolumeInfo srcData, DataStore srcStore) {
          when(srcStore.getId()).thenReturn(1L);
          when(srcData.getId()).thenReturn(1L);
  
          StoragePoolVO storagePoolVO = Mockito.mock(StoragePoolVO.class);
          when(storagePoolDao.findById(1L)).thenReturn(storagePoolVO);
          when(storagePoolVO.isManaged()).thenReturn(true);
  
          VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
          when(volumeDao.findById(1L)).thenReturn(volumeVO);
  
          when(volumeDetailsDao.findDetail(1L,  DiskTO.SCSI_NAA_DEVICE_ID)).thenReturn(null);
          when(volumeService.getChapInfo(srcData, srcStore)).thenReturn(null);
  
          StoragePoolDetailVO srcStoragePoolDetail = Mockito.mock(StoragePoolDetailVO.class);
          when(srcStoragePoolDetail.getValue()).thenReturn("610204d03e3ad60f");
          when(storagePoolDetailsDao.findDetail(1L, ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID)).thenReturn(srcStoragePoolDetail);
      }
  
      private void fillDestVolumeDetails(VolumeInfo srcData, DataStore srcStore) {
          when(srcStore.getId()).thenReturn(2L);
          when(srcData.getId()).thenReturn(2L);
  
          StoragePoolVO storagePoolVO = Mockito.mock(StoragePoolVO.class);
          when(storagePoolDao.findById(2L)).thenReturn(storagePoolVO);
          when(storagePoolVO.isManaged()).thenReturn(true);
  
          VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
          when(volumeDao.findById(2L)).thenReturn(volumeVO);
  
          when(volumeDetailsDao.findDetail(2L,  DiskTO.SCSI_NAA_DEVICE_ID)).thenReturn(null);
          when(volumeService.getChapInfo(srcData, srcStore)).thenReturn(null);
  
          StoragePoolDetailVO srcStoragePoolDetail = Mockito.mock(StoragePoolDetailVO.class);
          when(srcStoragePoolDetail.getValue()).thenReturn("7332760565f6340f");
          when(storagePoolDetailsDao.findDetail(2L, ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID)).thenReturn(srcStoragePoolDetail);
      }
  
      private Host prepareEndpointForVolumeOperation(VolumeInfo srcData) {
          VMInstanceVO instance = Mockito.mock(VMInstanceVO.class);
          when(srcData.getAttachedVmName()).thenReturn("i-2-VM");
          when(vmInstanceDao.findVMByInstanceName("i-2-VM")).thenReturn(instance);
          when(instance.getHostId()).thenReturn(4L);
          when(instance.getState()).thenReturn(VirtualMachine.State.Running);
          HostVO host = Mockito.mock(HostVO.class);
          when(hostDao.findById(4L)).thenReturn(host);
  
          return host;
      }
  
      @Test
      public void updateVolumeAfterCopyVolumeLiveMigrate() {
          VolumeInfo srcData = Mockito.mock(VolumeInfo.class);
          VolumeInfo destData = Mockito.mock(VolumeInfo.class);
  
          when(srcData.getId()).thenReturn(1L);
          when(destData.getId()).thenReturn(1L);
  
          VolumeVO volume = new VolumeVO("root", 1L, 1L, 1L, 1L, 1L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
          volume.setPoolId(2L);
          when(volumeDao.findById(1L)).thenReturn(volume);
          when(volumeDao.update(1L, volume)).thenReturn(true);
  
          scaleIOPrimaryDataStoreDriver.updateVolumeAfterCopyVolume(srcData, destData);
  
          Assert.assertEquals(Optional.of(2L), Optional.of(volume.getLastPoolId()));
      }
  
      @Test
      public void updateVolumeAfterCopyVolumeOffline() {
          VolumeInfo srcData = Mockito.mock(VolumeInfo.class);
          VolumeInfo destData = Mockito.mock(VolumeInfo.class);
  
          when(srcData.getId()).thenReturn(1L);
          when(destData.getId()).thenReturn(2L);
  
          VolumeVO volume = new VolumeVO("root", 1L, 1L, 1L, 1L, 1L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
          when(volumeDao.findById(1L)).thenReturn(volume);
          when(volumeDao.update(1L, volume)).thenReturn(true);
  
          scaleIOPrimaryDataStoreDriver.updateVolumeAfterCopyVolume(srcData, destData);
  
          Assert.assertNull(volume.get_iScsiName());
          Assert.assertNull(volume.getPath());
          Assert.assertNull(volume.getFolder());
      }
  
      @Test
      public void revertBlockCopyVolumeOperationsOnDeleteSuccess() throws Exception{
          //Either destination volume delete success or failure, DB operations should get revert
  
          VolumeInfo srcData = Mockito.mock(VolumeInfo.class);
          VolumeInfo destData = Mockito.mock(VolumeInfo.class);
          Host host = Mockito.mock(Host.class);
          String destVolumePath = "01b332b300000007:vol-11-b9e2-10ee";
  
          when(srcData.getId()).thenReturn(1L);
          when(srcData.getPoolId()).thenReturn(1L);
          when(destData.getId()).thenReturn(1L);
  
          when(srcData.getPath()).thenReturn("bec0ba7700000007:vol-11-6aef-10ee");
          when(srcData.getFolder()).thenReturn("921c364500000007");
          DataStore destStore = Mockito.mock(DataStore.class);
          when(destData.getDataStore()).thenReturn(destStore);
          doNothing().when(scaleIOPrimaryDataStoreDriver)
                  .revokeAccess(any(), any(), any());
  
          ScaleIOGatewayClient client = Mockito.mock(ScaleIOGatewayClient.class);
          doReturn(client).when(scaleIOPrimaryDataStoreDriver)
                  .getScaleIOClient(any(DataStore.class));
          when(client.deleteVolume(any())).thenReturn(true);
  
          VolumeVO volume = new VolumeVO("root", 1L, 1L, 1L, 1L, 1L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
          when(volumeDao.findById(1L)).thenReturn(volume);
          when(volumeDao.update(1L, volume)).thenReturn(true);
  
          scaleIOPrimaryDataStoreDriver.revertBlockCopyVolumeOperations(srcData, destData, host, destVolumePath);
  
          Assert.assertEquals("bec0ba7700000007:vol-11-6aef-10ee", volume.get_iScsiName());
          Assert.assertEquals("bec0ba7700000007:vol-11-6aef-10ee", volume.getPath());
          Assert.assertEquals("921c364500000007", volume.getFolder());
      }
  
      @Test
      public void revertBlockCopyVolumeOperationsOnDeleteFailure() throws Exception{
          //Either destination volume delete success or failure, DB operations should get revert
  
          VolumeInfo srcData = Mockito.mock(VolumeInfo.class);
          VolumeInfo destData = Mockito.mock(VolumeInfo.class);
          Host host = Mockito.mock(Host.class);
          String srcVolumePath = "bec0ba7700000007:vol-11-6aef-10ee";
          String destVolumePath = "01b332b300000007:vol-11-b9e2-10ee";
  
          when(srcData.getId()).thenReturn(1L);
          when(srcData.getPoolId()).thenReturn(1L);
          when(destData.getId()).thenReturn(1L);
  
          when(srcData.getPath()).thenReturn(srcVolumePath);
          when(srcData.getFolder()).thenReturn("921c364500000007");
          DataStore destStore = Mockito.mock(DataStore.class);
          when(destData.getDataStore()).thenReturn(destStore);
          doNothing().when(scaleIOPrimaryDataStoreDriver).revokeAccess(any(), any(), any());
  
          ScaleIOGatewayClient client = Mockito.mock(ScaleIOGatewayClient.class);
          doReturn(client).when(scaleIOPrimaryDataStoreDriver)
                  .getScaleIOClient(any(DataStore.class));
          when(client.deleteVolume(any())).thenReturn(false);
  
          VolumeVO volume = new VolumeVO("root", 1L, 1L, 1L, 1L, 1L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
          when(volumeDao.findById(1L)).thenReturn(volume);
          when(volumeDao.update(1L, volume)).thenReturn(true);
  
          scaleIOPrimaryDataStoreDriver.revertBlockCopyVolumeOperations(srcData, destData, host, destVolumePath);
  
          Assert.assertEquals(srcVolumePath, volume.get_iScsiName());
          Assert.assertEquals(srcVolumePath, volume.getPath());
          Assert.assertEquals("921c364500000007", volume.getFolder());
      }
  
      @Test
      public void deleteSourceVolumeSuccessScenarioAfterSuccessfulBlockCopy() throws Exception {
          // Either Volume deletion success or failure method should complete
  
          VolumeInfo srcData = Mockito.mock(VolumeInfo.class);
          Host host = Mockito.mock(Host.class);
          String srcVolumePath = "bec0ba7700000007:vol-11-6aef-10ee";
  
          DataStore srcStore = Mockito.mock(DataStore.class);
          DataTO volumeTO = Mockito.mock(DataTO.class);
          when(srcData.getDataStore()).thenReturn(srcStore);
          when(srcData.getTO()).thenReturn(volumeTO);
          when(volumeTO.getPath()).thenReturn(srcVolumePath);
          doNothing().when(scaleIOPrimaryDataStoreDriver).revokeVolumeAccess(any(), any(), any());
  
          ScaleIOGatewayClient client = Mockito.mock(ScaleIOGatewayClient.class);
          doReturn(client).when(scaleIOPrimaryDataStoreDriver)
                  .getScaleIOClient(any(DataStore.class));
          when(client.deleteVolume(any())).thenReturn(true);
  
          scaleIOPrimaryDataStoreDriver.deleteSourceVolumeAfterSuccessfulBlockCopy(srcData, host);
      }
  
      @Test
      public void deleteSourceVolumeFailureScenarioAfterSuccessfulBlockCopy() throws Exception {
          // Either Volume deletion success or failure method should complete
  
          VolumeInfo srcData = Mockito.mock(VolumeInfo.class);
          Host host = Mockito.mock(Host.class);
          String srcVolumePath = "bec0ba7700000007:vol-11-6aef-10ee";
  
          DataStore srcStore = Mockito.mock(DataStore.class);
          DataTO volumeTO = Mockito.mock(DataTO.class);
          when(srcData.getDataStore()).thenReturn(srcStore);
          when(srcData.getTO()).thenReturn(volumeTO);
          when(volumeTO.getPath()).thenReturn(srcVolumePath);
          String sdcId = "7332760565f6340f";
          doReturn(sdcId).when(scaleIOPrimaryDataStoreDriver).getConnectedSdc(srcStore, host);
  
          ScaleIOGatewayClient client = Mockito.mock(ScaleIOGatewayClient.class);
          doReturn(client).when(scaleIOPrimaryDataStoreDriver)
                  .getScaleIOClient(any(DataStore.class));
          doReturn(true).when(client).unmapVolumeFromSdc(any(), any());
          when(client.deleteVolume(any())).thenReturn(false);
  
          scaleIOPrimaryDataStoreDriver.deleteSourceVolumeAfterSuccessfulBlockCopy(srcData, host);
      }
  
      @Test
      public void deleteSourceVolumeFailureScenarioWhenNoSDCisFound() {
          // Either Volume deletion success or failure method should complete
  
          VolumeInfo srcData = Mockito.mock(VolumeInfo.class);
          Host host = Mockito.mock(Host.class);
          when(host.getId()).thenReturn(1L);
          String srcVolumePath = "bec0ba7700000007:vol-11-6aef-10ee";
  
          DataStore srcStore = Mockito.mock(DataStore.class);
          DataTO volumeTO = Mockito.mock(DataTO.class);
          when(srcData.getDataStore()).thenReturn(srcStore);
          when(srcData.getTO()).thenReturn(volumeTO);
          when(volumeTO.getPath()).thenReturn(srcVolumePath);
          String sdcId = "7332760565f6340f";
          doReturn(null).when(scaleIOPrimaryDataStoreDriver).getConnectedSdc(srcStore, host);
  
          scaleIOPrimaryDataStoreDriver.deleteSourceVolumeAfterSuccessfulBlockCopy(srcData, host);
      }
  
      @Test
      public void testCopyOfflineVolume() {
          when(configDao.getValue(Config.CopyVolumeWait.key())).thenReturn("3600");
  
          DataObject srcData = Mockito.mock(DataObject.class);
          DataTO srcDataTO = Mockito.mock(DataTO.class);
          when(srcData.getTO()).thenReturn(srcDataTO);
          DataObject destData = Mockito.mock(DataObject.class);
          DataTO destDataTO = Mockito.mock(DataTO.class);
          when(destData.getTO()).thenReturn(destDataTO);
          Host destHost = Mockito.mock(Host.class);
  
          doReturn(false).when(scaleIOPrimaryDataStoreDriver).anyVolumeRequiresEncryption(srcData, destData);
          RemoteHostEndPoint ep = Mockito.mock(RemoteHostEndPoint.class);
          remoteHostEndPointMock.when(() -> RemoteHostEndPoint.getHypervisorHostEndPoint(destHost)).thenReturn(ep);
          Answer answer = Mockito.mock(Answer.class);
          when(ep.sendMessage(any())).thenReturn(answer);
  
          Answer expectedAnswer = scaleIOPrimaryDataStoreDriver.copyOfflineVolume(srcData, destData, destHost);
  
          Assert.assertEquals(expectedAnswer, answer);
      }
  
      @Test
      public void testCopyOfflineVolumeFailureWhenNoEndpointFound() {
          when(configDao.getValue(Config.CopyVolumeWait.key())).thenReturn("3600");
  
          DataObject srcData = Mockito.mock(DataObject.class);
          DataTO srcDataTO = Mockito.mock(DataTO.class);
          when(srcData.getTO()).thenReturn(srcDataTO);
          DataObject destData = Mockito.mock(DataObject.class);
          DataTO destDataTO = Mockito.mock(DataTO.class);
          when(destData.getTO()).thenReturn(destDataTO);
          Host destHost = Mockito.mock(Host.class);
  
          doReturn(false).when(scaleIOPrimaryDataStoreDriver).anyVolumeRequiresEncryption(srcData, destData);
          remoteHostEndPointMock.when(() -> RemoteHostEndPoint.getHypervisorHostEndPoint(destHost)).thenReturn(null);
  
          Answer answer = scaleIOPrimaryDataStoreDriver.copyOfflineVolume(srcData, destData, destHost);
  
          Assert.assertEquals(false, answer.getResult());
      }
  
      @Test
      public void testGetVolumeSizeRequiredOnPool() {
          Assert.assertEquals(8L * (1024 * 1024 * 1024),
                  scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool(
                          52428800,
                          null,
                          false));
  
          Assert.assertEquals(8L * (1024 * 1024 * 1024),
                  scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool(
                          52428800,
                          52428800L,
                          true));
  
          Assert.assertEquals(16L * (1024 * 1024 * 1024),
                  scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool(
                          10L * (1024 * 1024 * 1024),
                          null,
                          true));
  
          Assert.assertEquals(16L * (1024 * 1024 * 1024),
                  scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool(
                          10L * (1024 * 1024 * 1024),
                          null,
                          false));
  
          Assert.assertEquals(16L * (1024 * 1024 * 1024),
                  scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool(
                          16L * (1024 * 1024 * 1024),
                          null,
                          false));
  
          Assert.assertEquals(16L * (1024 * 1024 * 1024),
                  scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool(
                          16L * (1024 * 1024 * 1024),
                          16L * (1024 * 1024 * 1024),
                          false));
  
          Assert.assertEquals(24L * (1024 * 1024 * 1024),
                  scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool(
                          16L * (1024 * 1024 * 1024),
                          16L * (1024 * 1024 * 1024),
                          true));
      }
  }
  