package org.ovirt.engine.api.restapi.resource;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import org.junit.Ignore;
import org.junit.Test;
import org.ovirt.engine.api.model.Link;
import org.ovirt.engine.api.model.Snapshot;
import org.ovirt.engine.api.model.CreationStatus;
import org.ovirt.engine.core.common.action.CreateAllSnapshotsFromVmParameters;
import org.ovirt.engine.core.common.action.MergeSnapshotParamenters;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.businessentities.DiskImage;
import org.ovirt.engine.core.common.businessentities.AsyncTaskStatus;
import org.ovirt.engine.core.common.businessentities.AsyncTaskStatusEnum;
import org.ovirt.engine.core.common.queries.GetAllDisksByVmIdParameters;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.compat.Guid;
import static org.easymock.classextension.EasyMock.expect;
public class BackendSnapshotsResourceTest
extends AbstractBackendCollectionResourceTest<Snapshot, DiskImage, BackendSnapshotsResource> {
static final Guid[] SNAPSHOT_IDS = GUIDS;
static final Guid[] IMAGE_IDS = { new Guid("55555555-5555-5555-5555-555555555555"),
new Guid("66666666-6666-6666-6666-666666666666"),
new Guid("77777777-7777-7777-7777-777777777777") };
static final Guid TASK_ID = new Guid("88888888-8888-8888-8888-888888888888");
static final Guid VM_ID = GUIDS[3];
public BackendSnapshotsResourceTest() {
super(new BackendSnapshotsResource(VM_ID), null, "");
}
@Test
@Ignore
@Override
public void testQuery() throws Exception {
}
@Test
public void testRemoveNotFound() throws Exception {
setUpGetEntityExpectations(1);
control.replay();
try {
collection.remove("c5cf0cd1-8580-44a8-b2e5-f6f9e4bc8f70");
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyNotFoundException(wae);
}
}
@Test
public void testRemove() throws Exception {
setUriInfo(setUpBasicUriExpectations());
setUpGetEntityExpectations(2);
setUpActionExpectations(VdcActionType.MergeSnapshot,
MergeSnapshotParamenters.class,
new String[] { "SourceVmSnapshotId", "DestVmSnapshotId", "VmId" },
new Object[] { SNAPSHOT_IDS[1], SNAPSHOT_IDS[2], VM_ID },
true,
true);
verifyRemove(collection.remove(SNAPSHOT_IDS[1].toString()));
}
@Test
public void testRemoveCantDo() throws Exception {
doTestBadRemove(false, true, CANT_DO);
}
@Test
public void testRemoveFailed() throws Exception {
doTestBadRemove(true, false, FAILURE);
}
protected void doTestBadRemove(boolean canDo, boolean success, String detail) throws Exception {
setUpGetEntityExpectations(2);
setUriInfo(setUpActionExpectations(VdcActionType.MergeSnapshot,
MergeSnapshotParamenters.class,
new String[] { "SourceVmSnapshotId", "DestVmSnapshotId", "VmId" },
new Object[] { SNAPSHOT_IDS[1], SNAPSHOT_IDS[2], VM_ID },
canDo,
success));
try {
collection.remove(SNAPSHOT_IDS[1].toString());
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyFault(wae, detail);
}
}
@Test
public void testAddAsyncPending() throws Exception {
doTestAddAsync(AsyncTaskStatusEnum.init, CreationStatus.PENDING);
}
@Test
public void testAddAsyncInProgress() throws Exception {
doTestAddAsync(AsyncTaskStatusEnum.running, CreationStatus.IN_PROGRESS);
}
@Test
public void testAddAsyncFinished() throws Exception {
doTestAddAsync(AsyncTaskStatusEnum.finished, CreationStatus.COMPLETE);
}
private void doTestAddAsync(AsyncTaskStatusEnum asyncStatus, CreationStatus creationStatus) throws Exception {
setUriInfo(setUpBasicUriExpectations());
setUpGetEntityExpectations(1);
setUpCreationExpectations(VdcActionType.CreateAllSnapshotsFromVm,
CreateAllSnapshotsFromVmParameters.class,
new String[] { "Description", "VmId" },
new Object[] { DESCRIPTIONS[0], VM_ID },
true,
true,
GUIDS[0],
asList(TASK_ID),
asList(new AsyncTaskStatus(asyncStatus)),
VdcQueryType.GetAllDisksByVmId,
GetAllDisksByVmIdParameters.class,
new String[] { "VmId" },
new Object[] { VM_ID },
getEntity(0));
Snapshot snapshot = new Snapshot();
snapshot.setDescription(DESCRIPTIONS[0]);
Response response = collection.add(snapshot);
assertEquals(202, response.getStatus());
assertTrue(response.getEntity() instanceof Snapshot);
verifyModel((Snapshot)response.getEntity(), 0);
Snapshot created = (Snapshot)response.getEntity();
assertNotNull(created.getCreationStatus());
assertEquals(creationStatus.value(), created.getCreationStatus().getState());
}
@Test
public void testAdd() throws Exception {
setUriInfo(setUpBasicUriExpectations());
setUpHttpHeaderExpectations("Expect", "201-created");
setUpGetEntityExpectations(1);
setUpGetEntityExpectations(1);
setUpCreationExpectations(VdcActionType.CreateAllSnapshotsFromVm,
CreateAllSnapshotsFromVmParameters.class,
new String[] { "Description", "VmId" },
new Object[] { DESCRIPTIONS[0], VM_ID },
true,
true,
GUIDS[0],
asList(GUIDS[1]),
asList(new AsyncTaskStatus(AsyncTaskStatusEnum.finished)),
VdcQueryType.GetAllDisksByVmId,
GetAllDisksByVmIdParameters.class,
new String[] { "VmId" },
new Object[] { VM_ID },
getEntity(0));
Snapshot snapshot = new Snapshot();
snapshot.setDescription(DESCRIPTIONS[0]);
Response response = collection.add(snapshot);
assertEquals(201, response.getStatus());
assertTrue(response.getEntity() instanceof Snapshot);
verifyModel((Snapshot)response.getEntity(), 0);
assertNull(((Snapshot)response.getEntity()).getCreationStatus());
}
@Test
public void testAddFromScratchCantDo() throws Exception {
doTestBadAddFromScratch(false, true, CANT_DO);
}
@Test
public void testAddFromScratchFailure() throws Exception {
doTestBadAddFromScratch(true, false, FAILURE);
}
private void doTestBadAddFromScratch(boolean canDo, boolean success, String detail)
throws Exception {
setUpGetEntityExpectations(1);
setUriInfo(setUpActionExpectations(VdcActionType.CreateAllSnapshotsFromVm,
CreateAllSnapshotsFromVmParameters.class,
new String[] { "Description", "VmId" },
new Object[] { DESCRIPTIONS[0], VM_ID },
canDo,
success));
Snapshot snapshot = new Snapshot();
snapshot.setDescription(DESCRIPTIONS[0]);
try {
collection.add(snapshot);
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyFault(wae, detail);
}
}
@Test
public void testAddIncompleteParameters() throws Exception {
Snapshot snapshot = new Snapshot();
setUriInfo(setUpBasicUriExpectations());
control.replay();
try {
collection.add(snapshot);
fail("expected WebApplicationException on incomplete parameters");
} catch (WebApplicationException wae) {
verifyIncompleteException(wae, "Snapshot", "add", "description");
}
}
@Override
protected List<Snapshot> getCollection() {
return collection.list().getSnapshots();
}
@Override
protected void setUpQueryExpectations(String query, Object failure) throws Exception {
assert(query.equals(""));
setUpEntityQueryExpectations(VdcQueryType.GetAllDisksByVmId,
GetAllDisksByVmIdParameters.class,
new String[] { "VmId" },
new Object[] { VM_ID },
setUpImages(),
failure);
control.replay();
}
protected void setUpGetEntityExpectations(int times) throws Exception {
while (times-- > 0) {
setUpEntityQueryExpectations(VdcQueryType.GetAllDisksByVmId,
GetAllDisksByVmIdParameters.class,
new String[] { "VmId" },
new Object[] { VM_ID },
setUpImages());
}
}
@Override
protected DiskImage getEntity(int index) {
DiskImage image = control.createMock(DiskImage.class);
expect(image.getId()).andReturn(IMAGE_IDS[index]).anyTimes();
ArrayList<DiskImage> snapshots = new ArrayList<DiskImage>();
Guid parentId = Guid.Empty.getValue();
for (int i = 0 ; i < NAMES.length ; i++) {
DiskImage snapshot = control.createMock(DiskImage.class);
Guid snapshotImageId = mangle(IMAGE_IDS[index], i);
expect(snapshot.getId()).andReturn(snapshotImageId).anyTimes();
expect(snapshot.getvm_snapshot_id()).andReturn(SNAPSHOT_IDS[i]).anyTimes();
expect(snapshot.getParentId()).andReturn(parentId).anyTimes();
expect(snapshot.getdescription()).andReturn(DESCRIPTIONS[i]).anyTimes();
snapshots.add(snapshot);
parentId = snapshotImageId;
}
expect(image.getSnapshots()).andReturn(snapshots).anyTimes();
return image;
}
static Guid mangle(Guid imageId, int index) {
return new Guid(imageId.toString().replace(imageId.toString().charAt(0),
Integer.toString(index).charAt(0)));
}
protected List<DiskImage> setUpImages() {
List<DiskImage> images = new ArrayList<DiskImage>();
for (int i = 0; i < NAMES.length; i++) {
images.add(getEntity(i));
}
return images;
}
protected void verifyModel(Snapshot model, int index) {
verifyModelSpecific(model, index);
verifyLinks(model);
}
static void verifyModelSpecific(Snapshot model, int index) {
for (Link link : model.getLinks()) {
if ("prev".equals(link.getRel())) {
assertTrue(link.getHref().startsWith("/api/vms/" + VM_ID + "/snapshots/"));
// assert that prev link points to the preceding snapshot ID
// (checking the difference between the last chars will suffice,
// as all snapshots IDs are sequences of repeated integers)
assertEquals(1, last(model.getId()) - last(link.getHref()));
}
}
if (model.getDisk() != null) {
assertEquals(model.getDisk().getId(), IMAGE_IDS[0].toString());
}
assertEquals(GUIDS[index].toString(), model.getId());
assertEquals(DESCRIPTIONS[index], model.getDescription());
}
protected static int last(String str) {
return Integer.valueOf(str.charAt(str.length() - 1));
}
}