package org.ovirt.engine.core.bll.snapshots; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anySet; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; import org.ovirt.engine.core.bll.BaseCommandTest; import org.ovirt.engine.core.bll.ValidateTestUtils; import org.ovirt.engine.core.bll.ValidationResult; import org.ovirt.engine.core.bll.validator.VmValidator; import org.ovirt.engine.core.bll.validator.storage.MultipleStorageDomainsValidator; import org.ovirt.engine.core.common.action.RemoveSnapshotParameters; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.common.businessentities.Snapshot; import org.ovirt.engine.core.common.businessentities.Snapshot.SnapshotType; import org.ovirt.engine.core.common.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.StoragePoolStatus; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.VmTemplate; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.Version; import org.ovirt.engine.core.dao.DiskImageDao; import org.ovirt.engine.core.dao.SnapshotDao; import org.ovirt.engine.core.dao.StoragePoolDao; import org.ovirt.engine.core.dao.VmTemplateDao; /** A test case for the {@link RemoveSnapshotCommand} class. */ public class RemoveSnapshotCommandTest extends BaseCommandTest { /** The command to test */ @Spy @InjectMocks private RemoveSnapshotCommand<RemoveSnapshotParameters> cmd = new RemoveSnapshotCommand<>(new RemoveSnapshotParameters(Guid.newGuid(), Guid.newGuid()), null); @Mock private VmTemplateDao vmTemplateDao; @Mock private DiskImageDao diskImageDao; @Mock private StoragePoolDao spDao; @Mock private SnapshotDao snapshotDao; @Spy private SnapshotsValidator snapshotValidator; private MultipleStorageDomainsValidator storageDomainsValidator; private static final Guid STORAGE_DOMAIN_ID = Guid.newGuid(); private static final Guid STORAGE_POOL_ID = Guid.newGuid(); @Before public void setUp() { mockVm(); VmValidator vmValidator = spy(new VmValidator(cmd.getVm())); doReturn(ValidationResult.VALID).when(vmValidator).vmNotHavingDeviceSnapshotsAttachedToOtherVms(anyBoolean()); doReturn(vmValidator).when(cmd).createVmValidator(any(VM.class)); doReturn(STORAGE_POOL_ID).when(cmd).getStoragePoolId(); mockSnapshot(SnapshotType.REGULAR); spySdValidator(); } private void mockVm() { VM vm = new VM(); vm.setId(Guid.newGuid()); vm.setStatus(VMStatus.Down); vm.setStoragePoolId(STORAGE_POOL_ID); doReturn(vm).when(cmd).getVm(); } private void mockCluster(Version compatabilityVersion) { Cluster cluster = new Cluster(); cluster.setId(Guid.newGuid()); cluster.setCompatibilityVersion(compatabilityVersion); doReturn(cluster).when(cmd).getCluster(); } private void mockSnapshot(SnapshotType snapshotType) { Snapshot snapshot = new Snapshot(); snapshot.setId(cmd.getParameters().getSnapshotId()); snapshot.setType(snapshotType); doReturn(snapshot).when(snapshotDao).get(snapshot.getId()); } private void spySdValidator() { Set<Guid> sdIds = new HashSet<>(Collections.singletonList(STORAGE_DOMAIN_ID)); storageDomainsValidator = spy(new MultipleStorageDomainsValidator(STORAGE_POOL_ID, sdIds)); doReturn(storageDomainsValidator).when(cmd).getStorageDomainsValidator(any(Guid.class), anySet()); doReturn(sdIds).when(cmd).getStorageDomainsIds(); doReturn(ValidationResult.VALID).when(storageDomainsValidator).allDomainsExistAndActive(); doReturn(ValidationResult.VALID).when(storageDomainsValidator).allDomainsWithinThresholds(); doReturn(ValidationResult.VALID).when(storageDomainsValidator).allDomainsHaveSpaceForMerge(anyList(), any()); } @Test public void testValidateImageNotInTemplateTrue() { when(vmTemplateDao.get(mockSourceImageAndGetId())).thenReturn(null); assertTrue("validation should succeed", cmd.validateImageNotInTemplate()); } @Test public void testValidateImageNotInTemplateFalse() { when(vmTemplateDao.get(mockSourceImageAndGetId())).thenReturn(new VmTemplate()); assertFalse("validation should succeed", cmd.validateImageNotInTemplate()); } @Test public void testValidateSnapshotNotActiveTrue() { mockSnapshot(SnapshotType.REGULAR); assertTrue("validation should succeed", cmd.validateSnapshotType()); } @Test public void testValidateSnapshotNotActiveFalse() { mockSnapshot(SnapshotType.ACTIVE); assertFalse("validation should fail", cmd.validateSnapshotType()); } @Test public void testValidateEnoughSpace() { prepareForVmValidatorTests(); spySdValidator(); cmd.getVm().setStatus(VMStatus.Up); List<DiskImage> parentSnapshots = mockDisksList(2); doReturn(parentSnapshots).when(cmd).getSourceImages(); ValidateTestUtils.runAndAssertValidateSuccess(cmd); } @Test public void testValidateNotEnoughSpace() { prepareForVmValidatorTests(); spySdValidator(); cmd.getVm().setStatus(VMStatus.Up); mockDisksList(2); when(storageDomainsValidator.allDomainsHaveSpaceForMerge(anyList(), any())) .thenReturn(new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN)); ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN); } private void prepareForVmValidatorTests() { StoragePool sp = new StoragePool(); sp.setId(STORAGE_POOL_ID); sp.setStatus(StoragePoolStatus.Up); cmd.setSnapshotName("someSnapshot"); doReturn(ValidationResult.VALID).when(snapshotValidator).vmNotDuringSnapshot(any(Guid.class)); doReturn(ValidationResult.VALID).when(snapshotValidator).vmNotInPreview(any(Guid.class)); doReturn(ValidationResult.VALID).when(snapshotValidator).snapshotExists(any(Guid.class), any(Guid.class)); doReturn(true).when(cmd).validateImages(); doReturn(sp).when(spDao).get(STORAGE_POOL_ID); doReturn(Collections.emptyList()).when(cmd).getSourceImages(); } @Test public void testValidateVmUpHostCapable() { prepareForVmValidatorTests(); cmd.getVm().setStatus(VMStatus.Up); ValidateTestUtils.runAndAssertValidateSuccess(cmd); } @Test public void testValidateVmDown() { prepareForVmValidatorTests(); cmd.getVm().setStatus(VMStatus.Down); ValidateTestUtils.runAndAssertValidateSuccess(cmd); } @Test public void testValidateVmMigrating() { prepareForVmValidatorTests(); cmd.getVm().setStatus(VMStatus.MigratingTo); ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_VM_IS_NOT_DOWN_OR_UP); } /** Mocks a call to {@link RemoveSnapshotCommand#getSourceImages()} and returns its image guid */ private Guid mockSourceImageAndGetId() { return mockSourceImage().getImageId(); } private DiskImage createDiskImage(Guid storageDomainId) { DiskImage image = new DiskImage(); image.setImageId(Guid.newGuid()); ArrayList<Guid> sdIds = new ArrayList<>(Collections.singletonList(storageDomainId)); image.setStorageIds(sdIds); return image; } /** Mocks a call to {@link RemoveSnapshotCommand#getSourceImages()} and returns the DiskImage */ private DiskImage mockSourceImage() { DiskImage image = createDiskImage(STORAGE_DOMAIN_ID); doReturn(Collections.singletonList(image)).when(cmd).getSourceImages(); when(diskImageDao.get(image.getImageId())).thenReturn(image); return image; } /** Mocks a call to {@link RemoveSnapshotCommand#getSourceImages()} and returns list of images */ private List<DiskImage> mockDisksList(int numberOfDisks) { List<DiskImage> disksList = new ArrayList<>(numberOfDisks); for (int index = 0; index < numberOfDisks; index++) { DiskImage image =createDiskImage(STORAGE_DOMAIN_ID); disksList.add(image); } doReturn(disksList).when(cmd).getSourceImages(); return disksList; } }