org.opengis.cite.iso19142.locking.LockFeatureTests Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ets-wfs20 Show documentation
Show all versions of ets-wfs20 Show documentation
Checks WFS 2.0 implementations for conformance to ISO 19142:2010.
package org.opengis.cite.iso19142.locking;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.logging.Level;
import javax.xml.namespace.QName;
import javax.xml.transform.dom.DOMSource;
import org.opengis.cite.iso19142.ETSAssert;
import org.opengis.cite.iso19142.ErrorMessage;
import org.opengis.cite.iso19142.ErrorMessageKeys;
import org.opengis.cite.iso19142.FeatureTypeInfo;
import org.opengis.cite.iso19142.Namespaces;
import org.opengis.cite.iso19142.ProtocolBinding;
import org.opengis.cite.iso19142.WFS2;
import org.opengis.cite.iso19142.util.ServiceMetadataUtils;
import org.opengis.cite.iso19142.util.TestSuiteLogger;
import org.opengis.cite.iso19142.util.WFSRequest;
import org.testng.Assert;
import org.testng.SkipException;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.sun.jersey.api.client.ClientResponse;
/**
* Tests the response to a LockFeature request that attempts to lock feature
* instances identified using one or more query expressions. A lock is active
* until it either expires (default duration is 300 s) or it is released by a
* subsequent transaction.
*
*
* Sources
*
*
* - ISO 19142:2010, cl. 12: LockFeature operation
* - ISO 19142:2010, cl. 12.4: Exceptions
* - ISO 19142:2010, cl. 15.2.3.1.1: Declaring support for locking
*
*/
public class LockFeatureTests extends LockingFixture {
private static Random randomIndex = new Random(System.currentTimeMillis());
/**
* Builds a DOM Document representing a LockFeature request entity.
*/
@BeforeMethod
public void buildSimpleLockFeatureRequest() {
this.reqEntity = WFSRequest.createRequestEntity("LockFeature");
}
/**
* [{@code Test}] An attempt to reset a non-existent lock should produce a
* service exception with error code "LockHasExpired" and HTTP status code
* 403 (Forbidden).
*
*
* Note: The WFS2 specification makes no distinction
* between a non-existent and an expired lock in this context. The error
* code {@code InvalidLockId} would seem more appropriate here but that may
* only appear in a Transaction response according to Table 3.
*
*
*
* Sources
*
*
* - ISO 19142:2010, cl. 12.2.4.2: lockId parameter
* - ISO 19142:2010, Table D.2
*
*/
@Test(description = "See ISO 19142: 12.2.4.2")
public void resetNonexistentLock() {
Map featureId = fetchRandomFeatureIdentifier(this.featureInfo);
String gmlId = featureId.keySet().iterator().next();
WFSRequest.appendStoredQuery(reqEntity, WFS2.QRY_GET_FEATURE_BY_ID,
Collections.singletonMap("id", (Object) gmlId));
reqEntity.getDocumentElement().setAttribute("lockId",
"lock-does-not-exist");
ClientResponse rsp = wfsClient.submitRequest(reqEntity,
ProtocolBinding.ANY);
this.rspEntity = rsp.getEntity(Document.class);
Assert.assertEquals(rsp.getStatus(),
ClientResponse.Status.FORBIDDEN.getStatusCode(),
ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
String xpath = "//ows:Exception[@exceptionCode = 'LockHasExpired']";
ETSAssert.assertXPath(xpath, this.rspEntity.getDocumentElement(), null);
}
/**
* [{@code Test}] Submits a request to lock a feature instance; within this
* interval an attempt to delete the instance without the correct lock
* identifier should fail with exception code {@code MissingParameterValue}.
*
*
* Sources
*
*
* - ISO 19142:2010, cl. 12.2.4.3: Lock expiry parameter
* - ISO 19142:2010, cl. 15.2.3.1.2: lockId parameter
*
*/
@Test(description = "See ISO 19142: 12.2.4.3, 15.2.3.1.2")
public void lockFeatureAndAttemptDelete() {
Map featureId = fetchRandomFeatureIdentifier(this.featureInfo);
String gmlId = featureId.keySet().iterator().next();
WFSRequest.appendStoredQuery(reqEntity, WFS2.QRY_GET_FEATURE_BY_ID,
Collections.singletonMap("id", (Object) gmlId));
reqEntity.getDocumentElement().setAttribute("expiry", "60");
ClientResponse rsp = wfsClient.submitRequest(reqEntity,
ProtocolBinding.ANY);
this.rspEntity = rsp.getEntity(Document.class);
Assert.assertEquals(rsp.getStatus(),
ClientResponse.Status.OK.getStatusCode(),
ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
ETSAssert
.assertXPath("//wfs:LockFeatureResponse", this.rspEntity, null);
Element lockRsp = (Element) this.rspEntity.getElementsByTagNameNS(
Namespaces.WFS, WFS2.LOCK_FEATURE_RSP).item(0);
String lockId = lockRsp.getAttribute("lockId");
Assert.assertFalse(lockId.isEmpty(), ErrorMessage.format(
ErrorMessageKeys.MISSING_INFOSET_ITEM, "@lockId"));
locks.add(lockId);
String xpath = String.format(
"//wfs:FeaturesLocked/fes:ResourceId/@rid = '%s'", gmlId);
ETSAssert.assertXPath(xpath, lockRsp, null);
Document trxResponse = wfsClient.delete(featureId, ProtocolBinding.ANY);
String xpath2 = "//ows:Exception[@exceptionCode = 'MissingParameterValue']";
ETSAssert.assertXPath(xpath2, trxResponse.getDocumentElement(), null);
}
/**
* [{@code Test}] A feature instance may be locked by only one lock. An
* attempt to establish another lock should fail with exception code
* {@code CannotLockAllFeatures} if lockAction = "ALL" (the default value).
*
*
* Sources
*
*
* - ISO 19142:2010, Table 18: Keywords for LockFeature KVP encoding
* - ISO 19142:2010, cl. 12.2.5: State machine for WFS locking
*
*/
@Test(description = "See ISO 19142: 12.2.3, 12.2.5")
public void lockFeatureAlreadyLocked() {
Map featureId = fetchRandomFeatureIdentifier(this.featureInfo);
String gmlId = featureId.keySet().iterator().next();
WFSRequest.appendStoredQuery(reqEntity, WFS2.QRY_GET_FEATURE_BY_ID,
Collections.singletonMap("id", (Object) gmlId));
reqEntity.getDocumentElement().setAttribute("expiry", "60");
ClientResponse rsp = wfsClient.submitRequest(reqEntity,
ProtocolBinding.ANY);
this.rspEntity = rsp.getEntity(Document.class);
Assert.assertEquals(rsp.getStatus(),
ClientResponse.Status.OK.getStatusCode(),
ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
Element lockRsp = (Element) this.rspEntity.getElementsByTagNameNS(
Namespaces.WFS, WFS2.LOCK_FEATURE_RSP).item(0);
locks.add(lockRsp.getAttribute("lockId"));
// try to lock it again (without specifying lockId)
reqEntity.getDocumentElement().setAttribute("expiry", "180");
rsp = wfsClient.submitRequest(reqEntity, ProtocolBinding.ANY);
this.rspEntity = rsp.getEntity(Document.class);
Assert.assertEquals(rsp.getStatus(),
ClientResponse.Status.BAD_REQUEST.getStatusCode(),
ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
String xpath = "//ows:Exception[@exceptionCode = 'CannotLockAllFeatures']";
ETSAssert.assertXPath(xpath, this.rspEntity.getDocumentElement(), null);
}
/**
* [{@code Test}] Locks all feature instances of a given type using default
* values for all locking options. If no data exist for a given feature type
* it is skipped. The response entity must include a lockId attribute and
* the wfs:FeaturesLocked element. The wfs:FeatureNotLocked element must not
* be present.
*
*
* Sources
*
*
* - ISO 19142:2010, cl. 12.3.2: XML-encoding
*
*
* @param binding
* The ProtocolBinding to use for the request.
* @param featureType
* A QName object denoting the feature type name.
*/
@Test(description = "See ISO 19142: 12.3.2", dataProvider = "protocol-featureType")
public void lockAllFeaturesByType(ProtocolBinding binding, QName featureType) {
if (!this.featureInfo.get(featureType).isInstantiated()) {
throw new SkipException("No data available for feature type "
+ featureType);
}
WFSRequest.appendSimpleQuery(this.reqEntity, featureType);
URI endpoint = ServiceMetadataUtils.getOperationEndpoint(
this.wfsMetadata, WFS2.LOCK_FEATURE, binding);
ClientResponse rsp = wfsClient.submitRequest(new DOMSource(reqEntity),
binding, endpoint);
this.rspEntity = extractBodyAsDocument(rsp, binding);
Assert.assertEquals(rsp.getStatus(),
ClientResponse.Status.OK.getStatusCode(),
ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
Element lockRsp = this.rspEntity.getDocumentElement();
Assert.assertEquals(lockRsp.getLocalName(), WFS2.LOCK_FEATURE_RSP,
ErrorMessage.get(ErrorMessageKeys.LOCAL_NAME));
String lockId = lockRsp.getAttribute("lockId");
Assert.assertFalse(lockId.isEmpty(), ErrorMessage.format(
ErrorMessageKeys.MISSING_INFOSET_ITEM,
"@lockId in " + lockRsp.getNodeName()));
locks.add(lockId);
ETSAssert.assertXPath("//wfs:FeaturesLocked", lockRsp, null);
ETSAssert.assertXPath("not(//wfs:FeaturesNotLocked)", lockRsp, null);
}
/**
* Obtains the system-assigned identifier of an instance of some randomly
* selected feature type.
*
* @param featureInfo
* A Map containing information about supported feature types,
* keyed by type name (QName).
* @return A Map containing at most a single entry that associates the
* (String) value of the gml:id attribute with the feature type name
* (QName); the map is empty if no data exist in the SUT.
*/
Map fetchRandomFeatureIdentifier(
Map featureInfo) {
Map featureId = new HashMap();
QName featureType = selectRandomFeatureType(featureInfo);
if (null != featureType) {
Document doc = wfsClient.getFeatureByType(featureType, 10, null);
NodeList features = doc.getElementsByTagNameNS(
featureType.getNamespaceURI(), featureType.getLocalPart());
Element feature = (Element) features.item(randomIndex
.nextInt(features.getLength()));
featureId.put(feature.getAttributeNS(Namespaces.GML, "id"),
featureType);
}
if (TestSuiteLogger.isLoggable(Level.FINER)) {
TestSuiteLogger.log(Level.FINER, featureId.toString());
}
return featureId;
}
/**
* Randomly selects a feature type name for which instances are available in
* the SUT.
*
* @param featureTypes
* A Map containing information about supported feature types,
* keyed by type name (QName).
* @return A QName object denoting the name of a feature type, or
* {@code null} if no data exist in the SUT.
*/
static QName selectRandomFeatureType(
Map featureTypes) {
List availableTypes = new ArrayList();
for (FeatureTypeInfo typeInfo : featureTypes.values()) {
if (typeInfo.isInstantiated()) {
availableTypes.add(typeInfo);
}
}
if (availableTypes.isEmpty()) {
return null;
}
FeatureTypeInfo availableType = availableTypes.get(randomIndex
.nextInt(availableTypes.size()));
return availableType.getTypeName();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy