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 com.cloud.storage.snapshot;
  
  import com.cloud.dc.DataCenter;
  import com.cloud.dc.DataCenterVO;
  import com.cloud.dc.dao.DataCenterDao;
  import com.cloud.event.ActionEventUtils;
  import com.cloud.exception.InvalidParameterValueException;
  import com.cloud.exception.PermissionDeniedException;
  import com.cloud.exception.ResourceAllocationException;
  import com.cloud.exception.ResourceUnavailableException;
  import com.cloud.org.Grouping;
  import com.cloud.storage.DataStoreRole;
  import com.cloud.storage.Snapshot;
  import com.cloud.storage.SnapshotPolicyVO;
  import com.cloud.storage.SnapshotVO;
  import com.cloud.storage.VolumeVO;
  import com.cloud.storage.dao.SnapshotDao;
  import com.cloud.storage.dao.SnapshotPolicyDao;
  import com.cloud.storage.dao.SnapshotZoneDao;
  import com.cloud.storage.dao.VolumeDao;
  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.dao.AccountDao;
  import com.cloud.utils.Pair;
  
  import com.cloud.utils.db.SearchBuilder;
  import com.cloud.utils.db.SearchCriteria;
  import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotPoliciesCmd;
  import org.apache.cloudstack.context.CallContext;
  import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
  import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
  import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
  import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotResult;
  import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
  import org.apache.cloudstack.framework.async.AsyncCallFuture;
  import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
  import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
  
  import org.junit.Assert;
  import org.junit.After;
  import org.junit.Before;
  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.junit.MockitoJUnitRunner;
  import org.mockito.stubbing.Answer;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.concurrent.ExecutionException;
  
  @RunWith(MockitoJUnitRunner.class)
  public class SnapshotManagerImplTest {
      @Mock
      AccountDao accountDao;
      @Mock
      SnapshotDao snapshotDao;
      @Mock
      AccountManager accountManager;
      @Mock
      SnapshotService snapshotService;
      @Mock
      SnapshotDataFactory snapshotFactory;
      @Mock
      ResourceLimitService resourceLimitService;
      @Mock
      DataCenterDao dataCenterDao;
      @Mock
      SnapshotDataStoreDao snapshotStoreDao;
      @Mock
      DataStoreManager dataStoreManager;
      @Mock
      SnapshotZoneDao snapshotZoneDao;
      @Mock
      VolumeDao volumeDao;
      @Mock
      SnapshotPolicyDao snapshotPolicyDao;
      @InjectMocks
      SnapshotManagerImpl snapshotManager = new SnapshotManagerImpl();
  
      @Before
      public void setUp() {
          snapshotManager._snapshotPolicyDao = snapshotPolicyDao;
          snapshotManager._volsDao = volumeDao;
          snapshotManager._accountMgr = accountManager;
      }
  
      @After
      public void tearDown() {
          CallContext.unregister();
      }
  
      @Test
      public void testGetSnapshotZoneImageStoreValid() {
          final long snapshotId = 1L;
          final long zoneId = 1L;
          final long storeId = 1L;
          SnapshotDataStoreVO ref = Mockito.mock(SnapshotDataStoreVO.class);
          Mockito.when(ref.getDataStoreId()).thenReturn(storeId);
          Mockito.when(ref.getRole()).thenReturn(DataStoreRole.Image);
          List<SnapshotDataStoreVO> snapshotStoreList = List.of(Mockito.mock(SnapshotDataStoreVO.class), ref);
          Mockito.when(dataStoreManager.getStoreZoneId(storeId, DataStoreRole.Image)).thenReturn(zoneId);
          Mockito.when(dataStoreManager.getDataStore(storeId, DataStoreRole.Image)).thenReturn(Mockito.mock(DataStore.class));
          Mockito.when(snapshotStoreDao.listReadyBySnapshot(snapshotId, DataStoreRole.Image)).thenReturn(snapshotStoreList);
          DataStore store = snapshotManager.getSnapshotZoneImageStore(snapshotId, zoneId);
          Assert.assertNotNull(store);
      }
  
      @Test
      public void testGetSnapshotZoneImageStoreNull() {
          final long snapshotId = 1L;
          final long zoneId = 1L;
          final long storeId = 1L;
          SnapshotDataStoreVO ref = Mockito.mock(SnapshotDataStoreVO.class);
          Mockito.when(ref.getDataStoreId()).thenReturn(storeId);
          Mockito.when(ref.getRole()).thenReturn(DataStoreRole.Image);
          List<SnapshotDataStoreVO> snapshotStoreList = List.of(ref);
          Mockito.when(dataStoreManager.getStoreZoneId(storeId, DataStoreRole.Image)).thenReturn(100L);
          Mockito.when(snapshotStoreDao.listReadyBySnapshot(snapshotId, DataStoreRole.Image)).thenReturn(snapshotStoreList);
          DataStore store = snapshotManager.getSnapshotZoneImageStore(snapshotId, zoneId);
          Assert.assertNull(store);
      }
  
      @Test(expected = InvalidParameterValueException.class)
      public void testGetStoreRefsAndZonesForSnapshotDeleteException() {
          final long snapshotId = 1L;
          final long zoneId = 1L;
          Mockito.when(dataCenterDao.findById(zoneId)).thenReturn(null);
          snapshotManager.getStoreRefsAndZonesForSnapshotDelete(snapshotId, zoneId);
      }
  
      @Test
      public void testGetStoreRefsAndZonesForSnapshotDeleteMultiZones() {
          final long snapshotId = 1L;
          SnapshotDataStoreVO ref = Mockito.mock(SnapshotDataStoreVO.class);
          Mockito.when(ref.getDataStoreId()).thenReturn(1L);
          Mockito.when(ref.getRole()).thenReturn(DataStoreRole.Image);
          SnapshotDataStoreVO ref1 = Mockito.mock(SnapshotDataStoreVO.class);
          Mockito.when(ref1.getDataStoreId()).thenReturn(2L);
          Mockito.when(ref1.getRole()).thenReturn(DataStoreRole.Image);
          List<SnapshotDataStoreVO> snapshotStoreList = List.of(ref, ref1);
          Mockito.when(snapshotStoreDao.findBySnapshotId(snapshotId)).thenReturn(snapshotStoreList);
          Mockito.when(dataStoreManager.getStoreZoneId(1L, DataStoreRole.Image)).thenReturn(100L);
          Mockito.when(dataStoreManager.getStoreZoneId(2L, DataStoreRole.Image)).thenReturn(101L);
          Pair<List<SnapshotDataStoreVO>, List<Long>> pair = snapshotManager.getStoreRefsAndZonesForSnapshotDelete(snapshotId, null);
          Assert.assertNotNull(pair.first());
          Assert.assertNotNull(pair.second());
          Assert.assertEquals(snapshotStoreList.size(), pair.first().size());
          Assert.assertEquals(2, pair.second().size());
      }
  
      @Test
      public void testGetStoreRefsAndZonesForSnapshotDeleteSingle() {
          final long snapshotId = 1L;
          final long zoneId = 1L;
          Mockito.when(dataCenterDao.findById(zoneId)).thenReturn(Mockito.mock(DataCenterVO.class));
          SnapshotDataStoreVO ref = Mockito.mock(SnapshotDataStoreVO.class);
          Mockito.when(ref.getDataStoreId()).thenReturn(1L);
          Mockito.when(ref.getRole()).thenReturn(DataStoreRole.Image);
          SnapshotDataStoreVO ref1 = Mockito.mock(SnapshotDataStoreVO.class);
          Mockito.when(ref1.getDataStoreId()).thenReturn(2L);
          Mockito.when(ref1.getRole()).thenReturn(DataStoreRole.Primary);
          SnapshotDataStoreVO ref2 = Mockito.mock(SnapshotDataStoreVO.class);
          Mockito.when(ref2.getDataStoreId()).thenReturn(3L);
          Mockito.when(ref2.getRole()).thenReturn(DataStoreRole.Image);
          List<SnapshotDataStoreVO> snapshotStoreList = List.of(ref, ref1, ref2);
          Mockito.when(snapshotStoreDao.findBySnapshotId(snapshotId)).thenReturn(snapshotStoreList);
          Mockito.when(dataStoreManager.getStoreZoneId(1L, DataStoreRole.Image)).thenReturn(zoneId);
          Mockito.when(dataStoreManager.getStoreZoneId(2L, DataStoreRole.Primary)).thenReturn(zoneId);
          Mockito.when(dataStoreManager.getStoreZoneId(3L, DataStoreRole.Image)).thenReturn(2L);
          Pair<List<SnapshotDataStoreVO>, List<Long>> pair = snapshotManager.getStoreRefsAndZonesForSnapshotDelete(snapshotId, zoneId);
          Assert.assertNotNull(pair.first());
          Assert.assertNotNull(pair.second());
          Assert.assertEquals(snapshotStoreList.size() - 1, pair.first().size());
          Assert.assertEquals(1, pair.second().size());
      }
      @Test
      public void testValidatePolicyZonesNoZones() {
          snapshotManager.validatePolicyZones(null, null, Mockito.mock(VolumeVO.class), Mockito.mock(Account.class));
      }
  
      @Test(expected = InvalidParameterValueException.class)
      public void testValidatePolicyZonesVolumeEdgeZone() {
          VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
          Mockito.when(volumeVO.getDataCenterId()).thenReturn(1L);
          DataCenterVO zone = Mockito.mock(DataCenterVO.class);
          Mockito.when(zone.getType()).thenReturn(DataCenter.Type.Edge);
          Mockito.when(dataCenterDao.findById(1L)).thenReturn(zone);
          snapshotManager.validatePolicyZones(List.of(1L), null, volumeVO, Mockito.mock(Account.class));
      }
  
      @Test(expected = InvalidParameterValueException.class)
      public void testValidatePolicyZonesNullZone() {
          VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
          Mockito.when(volumeVO.getDataCenterId()).thenReturn(1L);
          DataCenterVO zone = Mockito.mock(DataCenterVO.class);
          Mockito.when(zone.getType()).thenReturn(DataCenter.Type.Core);
          Mockito.when(dataCenterDao.findById(1L)).thenReturn(zone);
          Mockito.when(dataCenterDao.findById(2L)).thenReturn(null);
          snapshotManager.validatePolicyZones(List.of(2L), null, volumeVO, Mockito.mock(Account.class));
      }
  
      @Test(expected = PermissionDeniedException.class)
      public void testValidatePolicyZonesDisabledZone() {
          VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
          Mockito.when(volumeVO.getDataCenterId()).thenReturn(1L);
          DataCenterVO zone = Mockito.mock(DataCenterVO.class);
          Mockito.when(zone.getType()).thenReturn(DataCenter.Type.Core);
          Mockito.when(dataCenterDao.findById(1L)).thenReturn(zone);
          DataCenterVO zone1 = Mockito.mock(DataCenterVO.class);
          Mockito.when(zone1.getAllocationState()).thenReturn(Grouping.AllocationState.Disabled);
          Mockito.when(dataCenterDao.findById(2L)).thenReturn(zone1);
          Mockito.when(accountManager.isRootAdmin(Mockito.any())).thenReturn(false);
          snapshotManager.validatePolicyZones(List.of(2L), null, volumeVO, Mockito.mock(Account.class));
      }
  
      @Test(expected = InvalidParameterValueException.class)
      public void testValidatePolicyZonesEdgeZone() {
          VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
          Mockito.when(volumeVO.getDataCenterId()).thenReturn(1L);
          DataCenterVO zone = Mockito.mock(DataCenterVO.class);
          Mockito.when(zone.getType()).thenReturn(DataCenter.Type.Core);
          Mockito.when(dataCenterDao.findById(1L)).thenReturn(zone);
          DataCenterVO zone1 = Mockito.mock(DataCenterVO.class);
          Mockito.when(zone1.getType()).thenReturn(DataCenter.Type.Edge);
          Mockito.when(zone1.getAllocationState()).thenReturn(Grouping.AllocationState.Enabled);
          Mockito.when(dataCenterDao.findById(2L)).thenReturn(zone1);
          snapshotManager.validatePolicyZones(List.of(2L), null, volumeVO, Mockito.mock(Account.class));
      }
  
      @Test
      public void testValidatePolicyZonesValidZone() {
          VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
          Mockito.when(volumeVO.getDataCenterId()).thenReturn(1L);
          DataCenterVO zone = Mockito.mock(DataCenterVO.class);
          Mockito.when(zone.getType()).thenReturn(DataCenter.Type.Core);
          Mockito.when(dataCenterDao.findById(1L)).thenReturn(zone);
          DataCenterVO zone1 = Mockito.mock(DataCenterVO.class);
          Mockito.when(zone1.getType()).thenReturn(DataCenter.Type.Core);
          Mockito.when(zone1.getAllocationState()).thenReturn(Grouping.AllocationState.Enabled);
          Mockito.when(dataCenterDao.findById(2L)).thenReturn(zone1);
          snapshotManager.validatePolicyZones(List.of(2L), null, volumeVO, Mockito.mock(Account.class));
      }
  
      @Test
      public void testCopyNewSnapshotToZonesNoZones() {
          snapshotManager.copyNewSnapshotToZones(1L, 1L, new ArrayList<>());
      }
  
      @Test
      public void testCopyNewSnapshotToZones() {
          final long snapshotId = 1L;
          SnapshotVO snapshotVO = Mockito.mock(SnapshotVO.class);
          Mockito.when(snapshotVO.getId()).thenReturn(snapshotId);
          Mockito.when(snapshotVO.getAccountId()).thenReturn(1L);
          Mockito.when(snapshotDao.findById(snapshotId)).thenReturn(snapshotVO);
          final long zoneId = 1L;
          final long storeId = 1L;
          final long destZoneId = 2L;
          DataCenterVO zone = Mockito.mock(DataCenterVO.class);
          Mockito.when(zone.getId()).thenReturn(destZoneId);
          Mockito.when(dataCenterDao.findById(destZoneId)).thenReturn(zone);
          SnapshotDataStoreVO ref = Mockito.mock(SnapshotDataStoreVO.class);
          Mockito.when(ref.getDataStoreId()).thenReturn(storeId);
          Mockito.when(ref.getRole()).thenReturn(DataStoreRole.Image);
          List<SnapshotDataStoreVO> snapshotStoreList = List.of(Mockito.mock(SnapshotDataStoreVO.class), ref);
          Mockito.when(dataStoreManager.getStoreZoneId(storeId, DataStoreRole.Image)).thenReturn(zoneId);
          DataStore store = Mockito.mock(DataStore.class);
          Mockito.when(store.getId()).thenReturn(storeId);
          Mockito.when(dataStoreManager.getDataStore(storeId, DataStoreRole.Image)).thenReturn(store);
          Mockito.when(snapshotStoreDao.listReadyBySnapshot(snapshotId, DataStoreRole.Image)).thenReturn(snapshotStoreList);
          Mockito.when(snapshotFactory.getSnapshot(Mockito.anyLong(), Mockito.any())).thenReturn(Mockito.mock(SnapshotInfo.class));
          CreateCmdResult result = Mockito.mock(CreateCmdResult.class);
          Mockito.when(result.isFailed()).thenReturn(false);
          Mockito.when(result.getPath()).thenReturn("SOMEPATH");
          AsyncCallFuture<CreateCmdResult> future = Mockito.mock(AsyncCallFuture.class);
          Mockito.when(dataStoreManager.getImageStoresByScopeExcludingReadOnly(Mockito.any())).thenReturn(List.of(Mockito.mock(DataStore.class)));
          Mockito.when(dataStoreManager.getImageStoreWithFreeCapacity(Mockito.anyList())).thenReturn(Mockito.mock(DataStore.class));
          Mockito.when(snapshotStoreDao.findByStoreSnapshot(DataStoreRole.Image, 1L, 1L)).thenReturn(Mockito.mock(SnapshotDataStoreVO.class));
          AccountVO account = Mockito.mock(AccountVO.class);
          Mockito.when(account.getId()).thenReturn(1L);
          Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(account);
          SnapshotResult result1 = Mockito.mock(SnapshotResult.class);
          Mockito.when(result1.isFailed()).thenReturn(false);
          AsyncCallFuture<SnapshotResult> future1 = Mockito.mock(AsyncCallFuture.class);
          try {
              Mockito.doNothing().when(resourceLimitService).checkResourceLimit(Mockito.any(), Mockito.any(), Mockito.anyLong());
              Mockito.when(future.get()).thenReturn(result);
              Mockito.when(snapshotService.queryCopySnapshot(Mockito.any())).thenReturn(future);
              Mockito.when(future1.get()).thenReturn(result1);
              Mockito.when(snapshotService.copySnapshot(Mockito.any(SnapshotInfo.class), Mockito.anyString(), Mockito.any(DataStore.class))).thenReturn(future1);
          } catch (ResourceAllocationException | ResourceUnavailableException | ExecutionException | InterruptedException e) {
              Assert.fail(e.getMessage());
          }
          List<Long> addedZone = new ArrayList<>();
          Mockito.doAnswer((Answer<Void>) invocation -> {
              Long zoneId1 = (Long) invocation.getArguments()[1];
              addedZone.add(zoneId1);
              return null;
          }).when(snapshotZoneDao).addSnapshotToZone(Mockito.anyLong(), Mockito.anyLong());
          try (MockedStatic<ActionEventUtils> utilities = Mockito.mockStatic(ActionEventUtils.class)) {
              utilities.when(() -> ActionEventUtils.onStartedActionEvent(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(),
                      Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyLong())).thenReturn(1L);
              snapshotManager.copyNewSnapshotToZones(snapshotId, 1L, List.of(2L));
              Assert.assertEquals(1, addedZone.size());
          }
      }
  
      @Test(expected = InvalidParameterValueException.class)
      public void testGetCheckedSnapshotForCopyNoSnapshot() {
          SnapshotVO snapshotVO = Mockito.mock(SnapshotVO.class);
          snapshotManager.getCheckedSnapshotForCopy(snapshotVO, List.of(100L), null, false);
      }
  
      @Test(expected = InvalidParameterValueException.class)
      public void testGetCheckedSnapshotForCopyNoSnapshotBackup() {
          SnapshotVO snapshotVO = Mockito.mock(SnapshotVO.class);
          snapshotManager.getCheckedSnapshotForCopy(snapshotVO, List.of(100L), null, false);
      }
  
      @Test(expected = InvalidParameterValueException.class)
      public void testGetCheckedSnapshotForCopyNotOnSecondary() {
          final long snapshotId = 1L;
          SnapshotVO snapshotVO = Mockito.mock(SnapshotVO.class);
          Mockito.when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp);
          Mockito.when(snapshotVO.getLocationType()).thenReturn(Snapshot.LocationType.PRIMARY);
          snapshotManager.getCheckedSnapshotForCopy(snapshotVO, List.of(100L), null, false);
      }
  
      @Test(expected = InvalidParameterValueException.class)
      public void testGetCheckedSnapshotForCopyDestNotSpecified() {
          SnapshotVO snapshotVO = Mockito.mock(SnapshotVO.class);
          Mockito.when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp);
          snapshotManager.getCheckedSnapshotForCopy(snapshotVO, new ArrayList<>(), 1L, false);
      }
  
      @Test(expected = InvalidParameterValueException.class)
      public void testGetCheckedSnapshotForCopyDestContainsSource() {
          SnapshotVO snapshotVO = Mockito.mock(SnapshotVO.class);
          Mockito.when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp);
          Mockito.when(snapshotVO.getVolumeId()).thenReturn(1L);
          Mockito.when(volumeDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(VolumeVO.class));
          snapshotManager.getCheckedSnapshotForCopy(snapshotVO, List.of(100L, 1L), 1L, false);
      }
  
      @Test(expected = InvalidParameterValueException.class)
      public void testGetCheckedSnapshotForCopyNullSourceZone() {
          SnapshotVO snapshotVO = Mockito.mock(SnapshotVO.class);
          Mockito.when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp);
          Mockito.when(snapshotVO.getVolumeId()).thenReturn(1L);
          VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
          Mockito.when(volumeVO.getDataCenterId()).thenReturn(1L);
          Mockito.when(volumeDao.findById(Mockito.anyLong())).thenReturn(volumeVO);
          snapshotManager.getCheckedSnapshotForCopy(snapshotVO, List.of(100L, 101L), null, false);
      }
  
      @Test
      public void testGetCheckedSnapshotForCopyValid() {
          final Long zoneId = 1L;
          SnapshotVO snapshotVO = Mockito.mock(SnapshotVO.class);
          Mockito.when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp);
          Mockito.when(snapshotVO.getVolumeId()).thenReturn(1L);
          VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
          Mockito.when(volumeVO.getDataCenterId()).thenReturn(zoneId);
          Mockito.when(volumeDao.findById(Mockito.anyLong())).thenReturn(volumeVO);
          Mockito.when(dataCenterDao.findById(zoneId)).thenReturn(Mockito.mock(DataCenterVO.class));
          Pair<SnapshotVO, Long> result = snapshotManager.getCheckedSnapshotForCopy(snapshotVO, List.of(100L, 101L), null, false);
          Assert.assertNotNull(result.first());
          Assert.assertEquals(zoneId, result.second());
      }
  
      @Test
      public void testGetCheckedSnapshotForCopyNullDest() {
          final Long zoneId = 1L;
          SnapshotVO snapshotVO = Mockito.mock(SnapshotVO.class);
          Mockito.when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp);
          Mockito.when(snapshotVO.getVolumeId()).thenReturn(1L);
          VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
          Mockito.when(volumeVO.getDataCenterId()).thenReturn(zoneId);
          Mockito.when(volumeDao.findById(Mockito.anyLong())).thenReturn(volumeVO);
          Mockito.when(dataCenterDao.findById(zoneId)).thenReturn(Mockito.mock(DataCenterVO.class));
          Pair<SnapshotVO, Long> result = snapshotManager.getCheckedSnapshotForCopy(snapshotVO, List.of(100L, 101L), null, false);
          Assert.assertNotNull(result.first());
          Assert.assertEquals(zoneId, result.second());
      }
  
      @Test
      public void testGetCheckedDestinationZoneForSnapshotCopy() {
          long zoneId = 1L;
          DataCenterVO dataCenterVO = Mockito.mock(DataCenterVO.class);
          Mockito.when(dataCenterVO.getAllocationState()).thenReturn(Grouping.AllocationState.Enabled);
          Mockito.when(dataCenterVO.getType()).thenReturn(DataCenter.Type.Core);
          Mockito.when(dataCenterDao.findById(zoneId)).thenReturn(dataCenterVO);
          Assert.assertNotNull(snapshotManager.getCheckedDestinationZoneForSnapshotCopy(zoneId, false));
      }
  
      @Test
      public void testListSnapshotPolicies() {
          long volumeId = 42L;
          ListSnapshotPoliciesCmd cmd = Mockito.mock(ListSnapshotPoliciesCmd.class);
          Mockito.when(cmd.getVolumeId()).thenReturn(volumeId);
          Mockito.when(cmd.getId()).thenReturn(null);
          Mockito.when(cmd.getStartIndex()).thenReturn(0L);
          Mockito.when(cmd.getPageSizeVal()).thenReturn(10L);
  
          Account caller = Mockito.mock(Account.class);
          Mockito.when(caller.getId()).thenReturn(1L);
          CallContext.register(Mockito.mock(User.class), caller);
  
          SnapshotPolicyVO policy1 = Mockito.mock(SnapshotPolicyVO.class);
          SnapshotPolicyVO policy2 = Mockito.mock(SnapshotPolicyVO.class);
          List<SnapshotPolicyVO> mockPolicies = List.of(policy1, policy2);
  
          SearchBuilder<SnapshotPolicyVO> mockSearchBuilder = Mockito.mock(SearchBuilder.class);
          SearchBuilder<VolumeVO> mockVolumeSearchBuilder = Mockito.mock(SearchBuilder.class);
          SearchCriteria<SnapshotPolicyVO> mockSearchCriteria = Mockito.mock(SearchCriteria.class);
  
          Mockito.when(snapshotPolicyDao.createSearchBuilder()).thenReturn(mockSearchBuilder);
          Mockito.when(mockSearchBuilder.entity()).thenReturn(Mockito.mock(SnapshotPolicyVO.class));
          Mockito.when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
          Mockito.when(volumeDao.createSearchBuilder()).thenReturn(mockVolumeSearchBuilder);
          Mockito.when(mockVolumeSearchBuilder.entity()).thenReturn(Mockito.mock(VolumeVO.class));
          Mockito.when(snapshotPolicyDao.searchAndCount(Mockito.any(), Mockito.any())).thenReturn(new Pair<>(mockPolicies, 2));
  
          Pair<List<? extends SnapshotPolicy>, Integer> result = snapshotManager.listSnapshotPolicies(cmd);
  
          Assert.assertNotNull(result);
          Assert.assertEquals(2, result.first().size());
          Assert.assertEquals(Integer.valueOf(2), result.second());
          Assert.assertEquals(mockPolicies, result.first());
      }
  
      @Test
      public void testListSnapshotPolicies_NonRootAdmin() {
          ListSnapshotPoliciesCmd cmd = Mockito.mock(ListSnapshotPoliciesCmd.class);
          Mockito.when(cmd.getVolumeId()).thenReturn(1L);
          Mockito.when(cmd.getId()).thenReturn(null);
          Mockito.when(cmd.getStartIndex()).thenReturn(0L);
          Mockito.when(cmd.getPageSizeVal()).thenReturn(10L);
  
          Account caller = Mockito.mock(Account.class);
          Mockito.when(caller.getId()).thenReturn(2L);
          CallContext.register(Mockito.mock(User.class), caller);
  
          SnapshotPolicyVO policy1 = Mockito.mock(SnapshotPolicyVO.class);
          SnapshotPolicyVO policy2 = Mockito.mock(SnapshotPolicyVO.class);
          List<SnapshotPolicyVO> mockPolicies = List.of(policy1, policy2);
  
          SearchBuilder<SnapshotPolicyVO> mockSearchBuilder = Mockito.mock(SearchBuilder.class);
          SearchBuilder<VolumeVO> mockVolumeSearchBuilder = Mockito.mock(SearchBuilder.class);
          SearchCriteria<SnapshotPolicyVO> mockSearchCriteria = Mockito.mock(SearchCriteria.class);
  
          Mockito.when(snapshotPolicyDao.createSearchBuilder()).thenReturn(mockSearchBuilder);
          Mockito.when(mockSearchBuilder.entity()).thenReturn(Mockito.mock(SnapshotPolicyVO.class));
          Mockito.when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
          Mockito.when(volumeDao.createSearchBuilder()).thenReturn(mockVolumeSearchBuilder);
          Mockito.when(mockVolumeSearchBuilder.entity()).thenReturn(Mockito.mock(VolumeVO.class));
          Mockito.when(snapshotPolicyDao.searchAndCount(Mockito.any(), Mockito.any())).thenReturn(new Pair<>(mockPolicies, 2));
  
          Pair<List<? extends SnapshotPolicy>, Integer> result = snapshotManager.listSnapshotPolicies(cmd);
  
          Assert.assertNotNull(result);
          Assert.assertEquals(2, result.first().size());
          Assert.assertEquals(Integer.valueOf(2), result.second());
          Assert.assertEquals(mockPolicies, result.first());
      }
  
      @Test
      public void testListSnapshotPolicies_RootAdmin() {
          ListSnapshotPoliciesCmd cmd = Mockito.mock(ListSnapshotPoliciesCmd.class);
          Mockito.when(cmd.getVolumeId()).thenReturn(1L);
          Mockito.when(cmd.getId()).thenReturn(null);
          Mockito.when(cmd.getStartIndex()).thenReturn(0L);
          Mockito.when(cmd.getPageSizeVal()).thenReturn(10L);
  
          Account caller = Mockito.mock(Account.class);
          Mockito.when(caller.getId()).thenReturn(1L);
          CallContext.register(Mockito.mock(User.class), caller);
  
          SnapshotPolicyVO policy = Mockito.mock(SnapshotPolicyVO.class);
          SearchBuilder<SnapshotPolicyVO> mockSearchBuilder = Mockito.mock(SearchBuilder.class);
          SearchBuilder<VolumeVO> mockVolumeSearchBuilder = Mockito.mock(SearchBuilder.class);
          SearchCriteria<SnapshotPolicyVO> mockSearchCriteria = Mockito.mock(SearchCriteria.class);
  
          Mockito.when(snapshotPolicyDao.createSearchBuilder()).thenReturn(mockSearchBuilder);
          Mockito.when(mockSearchBuilder.entity()).thenReturn(Mockito.mock(SnapshotPolicyVO.class));
          Mockito.when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
          Mockito.when(volumeDao.createSearchBuilder()).thenReturn(mockVolumeSearchBuilder);
          Mockito.when(mockVolumeSearchBuilder.entity()).thenReturn(Mockito.mock(VolumeVO.class));
          Mockito.when(snapshotPolicyDao.searchAndCount(Mockito.any(), Mockito.any())).thenReturn(new Pair<>(List.of(policy), 1));
  
          Pair<List<? extends SnapshotPolicy>, Integer> result = snapshotManager.listSnapshotPolicies(cmd);
  
          Assert.assertNotNull(result);
          Assert.assertEquals(1, result.first().size());
          Assert.assertEquals(Integer.valueOf(1), result.second());
      }
  }
  