package org.geoserver.gss;
import org.geotools.data.Query;
import org.geotools.data.VersioningFeatureStore;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Id;
import org.w3c.dom.Document;
import static java.util.Collections.*;
import static org.custommonkey.xmlunit.XMLAssert.*;
import com.mockrunner.mock.web.MockHttpServletResponse;
public class GetDiffTest extends GSSTestSupport {
/**
* Tests that we asked for a out of order GetDiff: there has not been any PostDiff before it
*/
public void testGetDiffOutOfOrder() throws Exception {
MockHttpServletResponse response = postAsServletResponse(root(true), loadTextResource("GetDiffInitial.xml"));
validate(response);
Document dom = dom(response);
// print(dom);
checkOws10Exception(dom, "InvalidParameterValue", "fromVersion");
}
/**
* Checks we properly report back the layer is not known to the service
* @throws Exception
*/
public void testUnknownLayer() throws Exception {
MockHttpServletResponse response = postAsServletResponse(root(true),
loadTextResource("GetDiffUnknown.xml"));
validate(response);
Document dom = dom(response);
// print(dom);
checkOws10Exception(dom, "InvalidParameterValue", "typeName");
}
/**
* Checks we properly report back that revision is not known
* @throws Exception
*/
public void testFutureRevision() throws Exception {
MockHttpServletResponse response = postAsServletResponse(root(true),
loadTextResource("GetDiffFuture.xml"));
validate(response);
Document dom = dom(response);
// print(dom);
checkOws10Exception(dom, "InvalidParameterValue", "fromVersion");
}
public void testNoLocalChanges() throws Exception {
// run a postdiff that will merge some central changes. There are no local ones
MockHttpServletResponse response = postAsServletResponse(root(true),
loadTextResource("PostDiffInitial.xml"));
checkPostDiffSuccessResponse(response);
// now run a GetDiff that should get a positive, empty response
response = postAsServletResponse(root(true), loadTextResource("GetDiffInitial.xml"));
validate(response);
Document dom = dom(response);
// print(dom);
// we should have got back a GetDiffResponse with an empty transation in it
assertXpathEvaluatesTo("-1", "/gss:GetDiffResponse/@fromVersion", dom);
assertXpathEvaluatesTo("4", "/gss:GetDiffResponse/@toVersion", dom);
assertXpathEvaluatesTo("sf:restricted", "/gss:GetDiffResponse/@typeName", dom);
assertXpathExists("/gss:GetDiffResponse/gss:Changes", dom);
assertXpathEvaluatesTo("0", "count(/gss:GetDiffResponse/gss:Changes/*)", dom);
}
public void testCleanMerge() throws Exception {
// grab the datastore
VersioningFeatureStore restricted = (VersioningFeatureStore) synchStore.getFeatureSource("restricted");
SimpleFeatureType schema = restricted.getSchema();
// make the same changes as in the post diff
Id updateFilter = ff.id(singleton(ff.featureId("restricted.be7cafea-d0b7-4257-9b9c-1ed3de3f7ef4")));
restricted.modifyFeatures(schema.getDescriptor("cat"), -48, updateFilter);
// remove the third feature
Id removeFilter = ff.id(singleton(ff.featureId("restricted.d91fe390-bdc7-4b22-9316-2cd6c8737ef5")));
restricted.removeFeatures(removeFilter);
assertEquals(3, restricted.getCount(Query.ALL));
// get the response and do the basic checks
MockHttpServletResponse response = postAsServletResponse(root(true),
loadTextResource("PostDiffInitial.xml"));
checkPostDiffSuccessResponse(response);
// check there are no conflicts
assertEquals(0, gss.getActiveConflicts("restricted").size());
// run GetDiff
response = postAsServletResponse(root(true), loadTextResource("GetDiffInitial.xml"));
validate(response);
Document dom = dom(response);
// print(dom);
// we should have got back an empty transaction
// ... check the main element
assertXpathEvaluatesTo("-1", "/gss:GetDiffResponse/@fromVersion", dom);
assertXpathEvaluatesTo("6", "/gss:GetDiffResponse/@toVersion", dom);
assertXpathEvaluatesTo("sf:restricted", "/gss:GetDiffResponse/@typeName", dom);
// check the transaction is empty
assertXpathEvaluatesTo("0", "count(/gss:GetDiffResponse/gss:Changes/*)", dom);
}
public void testNoConflictingChanges() throws Exception {
// grab the datastore so that we can make some changes that will not generate conflicts
VersioningFeatureStore restricted = (VersioningFeatureStore) synchStore.getFeatureSource("restricted");
SimpleFeatureType schema = restricted.getSchema();
// modify the fourth feature, change its cat from 400 to 450
Id updateFilter = ff.id(singleton(ff.featureId("restricted.1b99be2b-2480-4742-ad52-95c294efda3b")));
restricted.modifyFeatures(schema.getDescriptor("cat"), 450, updateFilter);
// remove the third feature
Id removeFilter = ff.id(singleton(ff.featureId("restricted.c15e76ab-e44b-423e-8f85-f6d9927b878a")));
restricted.removeFeatures(removeFilter);
assertEquals(3, restricted.getCount(Query.ALL));
// execute the postDiff
MockHttpServletResponse response = postAsServletResponse(root(true),
loadTextResource("PostDiffInitial.xml"));
checkPostDiffSuccessResponse(response);
// check there are no conflicts
assertEquals(0, gss.getActiveConflicts("restricted").size());
// run GetDiff
response = postAsServletResponse(root(true), loadTextResource("GetDiffInitial.xml"));
validate(response);
Document dom = dom(response);
// print(dom);
// check the document contents are the expected ones
// ... check the main element
assertXpathEvaluatesTo("-1", "/gss:GetDiffResponse/@fromVersion", dom);
assertXpathEvaluatesTo("6", "/gss:GetDiffResponse/@toVersion", dom);
assertXpathEvaluatesTo("sf:restricted", "/gss:GetDiffResponse/@typeName", dom);
// check the transaction has two elements
assertXpathEvaluatesTo("2", "count(/gss:GetDiffResponse/gss:Changes/*)", dom);
// check the update one
assertXpathEvaluatesTo("sf:restricted", "/gss:GetDiffResponse/gss:Changes/wfs:Update/@typeName", dom);
assertXpathEvaluatesTo("1", "count(/gss:GetDiffResponse/gss:Changes/wfs:Update/ogc:Filter/ogc:FeatureId)", dom);
assertXpathEvaluatesTo("restricted.1b99be2b-2480-4742-ad52-95c294efda3b", "/gss:GetDiffResponse/gss:Changes/wfs:Update/ogc:Filter/ogc:FeatureId/@fid", dom);
assertXpathEvaluatesTo("1", "count(/gss:GetDiffResponse/gss:Changes/wfs:Update/wfs:Property)", dom);
assertXpathEvaluatesTo("cat", "/gss:GetDiffResponse/gss:Changes/wfs:Update/wfs:Property/wfs:Name", dom);
assertXpathEvaluatesTo("450", "/gss:GetDiffResponse/gss:Changes/wfs:Update/wfs:Property/wfs:Value", dom);
// check the delete one
assertXpathEvaluatesTo("sf:restricted", "/gss:GetDiffResponse/gss:Changes/wfs:Delete/@typeName", dom);
assertXpathEvaluatesTo("restricted.c15e76ab-e44b-423e-8f85-f6d9927b878a", "/gss:GetDiffResponse/gss:Changes/wfs:Delete/ogc:Filter/ogc:FeatureId/@fid", dom);
assertXpathEvaluatesTo("restricted.c15e76ab-e44b-423e-8f85-f6d9927b878a", "/gss:GetDiffResponse/gss:Changes/wfs:Delete/ogc:Filter/ogc:FeatureId/@fid", dom);
}
/**
* This time we mix some conflicting and non conflicting changes
*/
public void testConflicts() throws Exception {
VersioningFeatureStore restricted = (VersioningFeatureStore) synchStore.getFeatureSource("restricted");
SimpleFeatureType schema = restricted.getSchema();
// modify the fourth feature, change its cat from 400 to 450
Id updateFilter = ff.id(singleton(ff.featureId("restricted.1b99be2b-2480-4742-ad52-95c294efda3b")));
restricted.modifyFeatures(schema.getDescriptor("cat"), 450, updateFilter);
// a update that will generate a conflict
updateFilter = ff.id(singleton(ff.featureId("restricted.d91fe390-bdc7-4b22-9316-2cd6c8737ef5")));
restricted.modifyFeatures(schema.getDescriptor("cat"), 347, updateFilter);
// an update that will generate a clean merge
updateFilter = ff.id(singleton(ff.featureId("restricted.be7cafea-d0b7-4257-9b9c-1ed3de3f7ef4")));
restricted.modifyFeatures(schema.getDescriptor("cat"), -48, updateFilter);
// execute the postDiff
MockHttpServletResponse response = postAsServletResponse(root(true),
loadTextResource("PostDiffInitial.xml"));
checkPostDiffSuccessResponse(response);
// check there is one conflict and one clean merge
assertEquals(1, gss.getActiveConflicts("restricted").size());
assertEquals(1, gss.getCleanMerges("restricted", 7).size());
// run GetDiff
response = postAsServletResponse(root(true), loadTextResource("GetDiffInitial.xml"));
validate(response);
Document dom = dom(response);
// print(dom);
// check the document contents are the expected ones
// ... check the main element
assertXpathEvaluatesTo("-1", "/gss:GetDiffResponse/@fromVersion", dom);
assertXpathEvaluatesTo("7", "/gss:GetDiffResponse/@toVersion", dom);
assertXpathEvaluatesTo("sf:restricted", "/gss:GetDiffResponse/@typeName", dom);
// ... check we get only one change, the non conflicting one
assertXpathEvaluatesTo("1", "count(/gss:GetDiffResponse/gss:Changes)", dom);
// check the update one
assertXpathEvaluatesTo("sf:restricted", "/gss:GetDiffResponse/gss:Changes/wfs:Update/@typeName", dom);
assertXpathEvaluatesTo("1", "count(/gss:GetDiffResponse/gss:Changes/wfs:Update/ogc:Filter/ogc:FeatureId)", dom);
assertXpathEvaluatesTo("restricted.1b99be2b-2480-4742-ad52-95c294efda3b", "/gss:GetDiffResponse/gss:Changes/wfs:Update/ogc:Filter/ogc:FeatureId/@fid", dom);
assertXpathEvaluatesTo("1", "count(/gss:GetDiffResponse/gss:Changes/wfs:Update/wfs:Property)", dom);
assertXpathEvaluatesTo("cat", "/gss:GetDiffResponse/gss:Changes/wfs:Update/wfs:Property/wfs:Name", dom);
assertXpathEvaluatesTo("450", "/gss:GetDiffResponse/gss:Changes/wfs:Update/wfs:Property/wfs:Value", dom);
}
}