Skip to content

Commit

Permalink
Merge pull request #3138 from sbrunner/limit
Browse files Browse the repository at this point in the history
Add and fix WFS server MAXFEATURES test
  • Loading branch information
nyalldawson committed May 30, 2016
2 parents 3bdbf79 + 47cf924 commit ddd37ad
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 17 deletions.
27 changes: 16 additions & 11 deletions src/server/qgswfsserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,8 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
mErrors = QStringList();
mTypeNames = QStringList();

long maxFeat = 0;
long maxFeatures = -1;
long maxFeatures = 0;
bool hasFeatureLimit = false;
long startIndex = 0;
long featureCounter = 0;
int layerPrec = 8;
Expand All @@ -432,9 +432,14 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
{
QDomElement docElem = doc.documentElement();
if ( docElem.hasAttribute( "maxFeatures" ) )
{
hasFeatureLimit = true;
maxFeatures = docElem.attribute( "maxFeatures" ).toLong();
}
if ( docElem.hasAttribute( "startIndex" ) )
{
startIndex = docElem.attribute( "startIndex" ).toLong();
}

QDomNodeList queryNodes = docElem.elementsByTagName( "Query" );
QDomElement queryElem;
Expand Down Expand Up @@ -630,7 +635,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
req.setSubsetOfAttributes( attrIndexes );

QgsFeatureIterator fit = layer->getFeatures( req );
while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
{
if ( featureCounter == startIndex )
startGetFeature( request, format, layerPrec, layerCrs, &searchRect );
Expand All @@ -652,7 +657,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
{
throw QgsMapServiceException( "RequestNotWellFormed", filter->parserErrorString() );
}
while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
{
expressionContext.setFeature( feature );

Expand All @@ -679,7 +684,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
}
else
{
while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
{
if ( featureCounter == startIndex )
startGetFeature( request, format, layerPrec, layerCrs, &searchRect );
Expand Down Expand Up @@ -819,8 +824,8 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
{
QString mfString = mfIt.value();
bool mfOk;
hasFeatureLimit = true;
maxFeatures = mfString.toLong( &mfOk, 10 );
maxFeat = mfString.toLong( &mfOk, 10 );
}

//read STARTINDEX
Expand Down Expand Up @@ -983,7 +988,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
{
throw QgsMapServiceException( "RequestNotWellFormed", QString( "Expression filter error message: %1." ).arg( filter->parserErrorString() ) );
}
while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
{
expressionContext.setFeature( feature );
QVariant res = filter->evaluate( &expressionContext );
Expand Down Expand Up @@ -1067,7 +1072,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
req.setSubsetOfAttributes( attrIndexes );

QgsFeatureIterator fit = layer->getFeatures( req );
while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
{
if ( featureCounter == startIndex )
startGetFeature( request, format, layerPrec, layerCrs, &searchRect );
Expand Down Expand Up @@ -1108,7 +1113,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
}
req.setSubsetOfAttributes( attrIndexes );
QgsFeatureIterator fit = layer->getFeatures( req );
while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
{
expressionContext.setFeature( feature );
QVariant res = filter->evaluate( &expressionContext );
Expand Down Expand Up @@ -1154,7 +1159,7 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
}
req.setSubsetOfAttributes( attrIndexes );
QgsFeatureIterator fit = layer->getFeatures( req );
while ( fit.nextFeature( feature ) && ( maxFeatures == -1 || featureCounter < maxFeat + startIndex ) )
while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
{
mErrors << QString( "The feature %2 of layer for the TypeName '%1'" ).arg( tnStr ).arg( featureCounter );
if ( featureCounter == startIndex )
Expand Down Expand Up @@ -1375,7 +1380,7 @@ void QgsWFSServer::endGetFeature( QgsRequestHandler& request, const QString& for
}
else
{
fcString = "</wfs:FeatureCollection>";
fcString = "</wfs:FeatureCollection>\n";
result = fcString.toUtf8();
request.endGetFeatureResponse( &result );
fcString = "";
Expand Down
62 changes: 58 additions & 4 deletions tests/src/python/test_qgsserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,19 @@ def wfs_getfeature_compare(self, requestid, request):

query_string = 'MAP=%s&SERVICE=WFS&VERSION=1.0.0&REQUEST=%s' % (urllib.quote(project), request)
header, body = [str(_v) for _v in self.server.handleRequest(query_string)]
self.result_compare(
'wfs_getfeature_' + requestid + '.txt',
u"request %s failed.\n Query: %s" % (
query_string,
request,
),
header, body
)

def result_compare(self, file_name, error_msg_header, header, body):
self.assert_headers(header, body)
response = header + body
f = open(self.testdata_path + 'wfs_getfeature_' + requestid + '.txt')
f = open(self.testdata_path + file_name)
expected = f.read()
f.close()
# Store the output for debug or to regenerate the reference documents:
Expand All @@ -298,20 +308,64 @@ def wfs_getfeature_compare(self, requestid, request):
"""
response = re.sub(RE_STRIP_PATH, '', response)
expected = re.sub(RE_STRIP_PATH, '', expected)
self.assertEqual(response, expected, msg=u"request %s failed.\n Query: %s\n Expected:\n%s\n\n Response:\n%s"
% (query_string,
request,
self.assertEqual(response, expected, msg=u"%s\n Expected:\n%s\n\n Response:\n%s"
% (error_msg_header,
unicode(expected, errors='replace'),
unicode(response, errors='replace')))

def test_getfeature(self):
tests = []
tests.append(('nobbox', u'GetFeature&TYPENAME=testlayer'))
tests.append(('startindex2', u'GetFeature&TYPENAME=testlayer&STARTINDEX=2'))
tests.append(('limit2', u'GetFeature&TYPENAME=testlayer&MAXFEATURES=2'))
tests.append(('start1_limit1', u'GetFeature&TYPENAME=testlayer&MAXFEATURES=1&STARTINDEX=1'))

for id, req in tests:
self.wfs_getfeature_compare(id, req)

def wfs_getfeature_post_compare(self, requestid, request):
project = self.testdata_path + "test+project_wfs.qgs"
assert os.path.exists(project), "Project file not found: " + project

query_string = 'MAP={}'.format(urllib.quote(project))
self.server.putenv("REQUEST_METHOD", "POST")
self.server.putenv("REQUEST_BODY", request)
header, body = self.server.handleRequest(query_string)
self.server.putenv("REQUEST_METHOD", '')
self.server.putenv("REQUEST_BODY", '')

self.result_compare(
'wfs_getfeature_{}.txt'.format(requestid),
"GetFeature in POST for '{}' failed.".format(requestid),
header, body,
)

def test_getfeature_post(self):
template = """<?xml version="1.0" encoding="UTF-8"?>
<wfs:GetFeature service="WFS" version="1.0.0" {} xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
<wfs:Query typeName="testlayer" xmlns:feature="http://www.qgis.org/gml">
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:BBOX>
<ogc:PropertyName>geometry</ogc:PropertyName>
<gml:Envelope xmlns:gml="http://www.opengis.net/gml">
<gml:lowerCorner>8 44</gml:lowerCorner>
<gml:upperCorner>9 45</gml:upperCorner>
</gml:Envelope>
</ogc:BBOX>
</ogc:Filter>
</wfs:Query>
</wfs:GetFeature>
"""

tests = []
tests.append(('nobbox', template.format("")))
tests.append(('startindex2', template.format('startIndex="2"')))
tests.append(('limit2', template.format('maxFeatures="2"')))
tests.append(('start1_limit1', template.format('startIndex="1" maxFeatures="1"')))

for id, req in tests:
self.wfs_getfeature_post_compare(id, req)

def test_getLegendGraphics(self):
"""Test that does not return an exception but an image"""
parms = {
Expand Down
42 changes: 42 additions & 0 deletions tests/testdata/qgis_server/wfs_getfeature_limit2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
Content-Type: text/xml; charset=utf-8

<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qgs="http://www.qgis.org/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://www.qgis.org/gml http:?SERVICE=WFS&amp;VERSION=1.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=testlayer&amp;OUTPUTFORMAT=XMLSCHEMA"><gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">8.2034593,44.90139483 8.203547,44.90148254</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<qgs:testlayer fid="testlayer.0">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">8.20349634,44.90148253 8.20349634,44.90148253</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<gml:Point srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">8.20349634,44.90148253</gml:coordinates>
</gml:Point>
</qgs:geometry>
<qgs:id>1</qgs:id>
<qgs:name>one</qgs:name>
<qgs:utf8nameè>one èé</qgs:utf8nameè>
</qgs:testlayer>
</gml:featureMember>
<gml:featureMember>
<qgs:testlayer fid="testlayer.1">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">8.20354699,44.90143568 8.20354699,44.90143568</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<gml:Point srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">8.20354699,44.90143568</gml:coordinates>
</gml:Point>
</qgs:geometry>
<qgs:id>2</qgs:id>
<qgs:name>two</qgs:name>
<qgs:utf8nameè>two àò</qgs:utf8nameè>
</qgs:testlayer>
</gml:featureMember>
</wfs:FeatureCollection>
2 changes: 1 addition & 1 deletion tests/testdata/qgis_server/wfs_getfeature_nobbox.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ Content-Type: text/xml; charset=utf-8
<qgs:utf8nameè>three èé↓</qgs:utf8nameè>
</qgs:testlayer>
</gml:featureMember>
</wfs:FeatureCollection>
</wfs:FeatureCollection>
25 changes: 25 additions & 0 deletions tests/testdata/qgis_server/wfs_getfeature_start1_limit1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Content-Type: text/xml; charset=utf-8

<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qgs="http://www.qgis.org/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://www.qgis.org/gml http:?SERVICE=WFS&amp;VERSION=1.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=testlayer&amp;OUTPUTFORMAT=XMLSCHEMA"><gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">8.2034593,44.90139483 8.203547,44.90148254</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<qgs:testlayer fid="testlayer.1">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">8.20354699,44.90143568 8.20354699,44.90143568</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<gml:Point srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">8.20354699,44.90143568</gml:coordinates>
</gml:Point>
</qgs:geometry>
<qgs:id>2</qgs:id>
<qgs:name>two</qgs:name>
<qgs:utf8nameè>two àò</qgs:utf8nameè>
</qgs:testlayer>
</gml:featureMember>
</wfs:FeatureCollection>
2 changes: 1 addition & 1 deletion tests/testdata/qgis_server/wfs_getfeature_startindex2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ Content-Type: text/xml; charset=utf-8
<qgs:utf8nameè>three èé↓</qgs:utf8nameè>
</qgs:testlayer>
</gml:featureMember>
</wfs:FeatureCollection>
</wfs:FeatureCollection>

0 comments on commit ddd37ad

Please sign in to comment.