Skip to content

Commit

Permalink
Merge pull request #533 from EOxServer/wcs-geteocoverageset-xml
Browse files Browse the repository at this point in the history
Wcs geteocoverageset xml
  • Loading branch information
constantinius committed Aug 12, 2022
2 parents 09ba036 + baabdf8 commit a325b28
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 15 deletions.
77 changes: 77 additions & 0 deletions autotest/autotest_services/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
from lxml import etree
import tempfile
import mimetypes
from zipfile import ZipFile, ZipInfo
from tarfile import TarFile, TarInfo
from base64 import b64decode
import numpy as np
try:
Expand Down Expand Up @@ -1143,6 +1145,7 @@ def testCoverageCount(self):
)
self.assertEqual(len(dss_ids), self.getExpectedDatasetSeriesCount())


class WCS20DescribeEOCoverageSetSectionsTestCase(XMLTestCase):
def getExpectedSections(self):
return []
Expand Down Expand Up @@ -1309,3 +1312,77 @@ def tearDown(self):
os.remove(self.tmppath)
except AttributeError:
pass


class StreamingContentTestCase(OWSTestCase):
"""
Base class for test cases that expects streamed output.
"""
def getResponseData(self):
if not hasattr(self, 'responseData'):
self.responseData = BytesIO(b''.join(self.response.streaming_content))
self.responseData.seek(0)
return self.responseData

@tag('archive')
class WCSGetEOCoverageArchiveTestCase(StreamingContentTestCase):
"""
Base class for test cases that expects archive output.
"""
expectedContentType:str = None
def getArchiveMembers(self):
"""returning archive FileInfo of files contained in the request archive
Raises:
ValueError: When content-type is not expected archive type.
Returns:
list: list of FileInfo (TarFile or ZipFile) objects.
"""
response = self.getResponseData()
# check response type and use Class accordingly
content_type = self.getResponseHeader("Content-Type")
if content_type in ['application/zip']:
with ZipFile(response, 'r') as archive:
members = archive.infolist()
return members
elif content_type in ['application/x-compressed-tar']:
# if used as context-manager, compression modes (r:gz, r:bz2 are not allowed)
archive = TarFile.open(fileobj=response, mode='r')
members = archive.getmembers()
archive.close()
return members
else:
raise ValueError('Content-Type %s not recognized as archive' % (
content_type,
))

def testHeader(self):
self.assertEqual(self.getResponseHeader("Content-Type"), self.expectedContentType)

def fileExistsInArchive(self, f:str):
"""Returns if filepath is present in the archive
Args:
f (str): filename to search
"""
members = self.getArchiveMembers()
for member in members:
if isinstance(member, TarInfo) and f in member.name:
return True
if isinstance(member, ZipInfo) and f in member.filename:
return True
return False


class WCS20GetEOCoverageSetPagingTestCase(WCSGetEOCoverageArchiveTestCase):
files_should_exist:list = []
files_should_not_exist:list = []

def testCoveragesPresent(self):
"""
Tests expected present and missing files in archive.
"""
for item in self.files_should_exist:
self.assertTrue(self.fileExistsInArchive(item))
for item in self.files_should_not_exist:
self.assertFalse(self.fileExistsInArchive(item))
54 changes: 54 additions & 0 deletions autotest/autotest_services/tests/wcs/test_v20.py
Original file line number Diff line number Diff line change
Expand Up @@ -1716,3 +1716,57 @@ def testStatus(self):
def testContentTypeIsHtml(self):
content_type = self.response.get("Content-Type")
self.assertEqual(content_type, "text/html")


#===============================================================================
# WCS GetEOCoverageSet 2.0.1: Paging testcases
#===============================================================================

@tag('wcs', 'wcs20')
class WCS20GetEOCoverageSetDatasetPagingTestCase(testbase.WCS20GetEOCoverageSetPagingTestCase):
"""
Tests if only the second coverage is put in the archive when paging is used.
"""
files_should_exist = ['MER_FRS_1PNPDE20060822_092058_000001972050_00308_23408_0077_uint16_reduced_compressed']
files_should_not_exist = ['MER_FRS_1PNPDE20060816_090929_000001972050_00222_23322_0058_uint16_reduced_compressed']
expectedContentType = 'application/x-compressed-tar'
def getRequest(self):
params = 'service=WCS&version=2.0.1&request=GetEOCoverageSet&eoId=MER_FRS_1PNPDE20060816_090929_000001972050_00222_23322_0058_uint16_reduced_compressed,MER_FRS_1PNPDE20060822_092058_000001972050_00308_23408_0077_uint16_reduced_compressed&count=1&startIndex=1'
return (params, "kvp")


@tag('wcs', 'wcs20')
class WCS20GetEOCoverageSetDatasetPagingXMLTestCase(testbase.WCS20GetEOCoverageSetPagingTestCase):
"""
Tests if only the second coverage is put in the archive when paging is used. XML input.
"""
files_should_exist = ['MER_FRS_1PNPDE20060822_092058_000001972050_00308_23408_0077_uint16_reduced_compressed']
files_should_not_exist = ['MER_FRS_1PNPDE20060816_090929_000001972050_00222_23322_0058_uint16_reduced_compressed']
expectedContentType = 'application/x-compressed-tar'
def getRequest(self):
params = """<wcseo:GetEOCoverageSet service="WCS" version="2.0.1"
xmlns:wcseo="http://www.opengis.net/wcs/wcseo/1.1"
xmlns:wcs="http://www.opengis.net/wcs/2.0"
count="1"
startIndex="1">
<wcseo:eoId>MER_FRS_1PNPDE20060816_090929_000001972050_00222_23322_0058_uint16_reduced_compressed</wcseo:eoId>
<wcseo:eoId>MER_FRS_1PNPDE20060822_092058_000001972050_00308_23408_0077_uint16_reduced_compressed</wcseo:eoId>
</wcseo:GetEOCoverageSet>"""
return (params, "xml")


@tag('wcs', 'wcs20')
class WCS20GetEOCoverageSetDatasetZIPXMLTestCase(testbase.WCS20GetEOCoverageSetPagingTestCase):
"""
Tests if a coverage is put in a ZIP archive. XML input.
"""
files_should_exist = ['MER_FRS_1PNPDE20060816_090929_000001972050_00222_23322_0058_uint16_reduced_compressed']
expectedContentType = 'application/zip'
def getRequest(self):
params = """<wcseo:GetEOCoverageSet service="WCS" version="2.0.1"
xmlns:wcseo="http://www.opengis.net/wcs/wcseo/1.1"
xmlns:wcs="http://www.opengis.net/wcs/2.0">
<wcseo:eoId>MER_FRS_1PNPDE20060816_090929_000001972050_00222_23322_0058_uint16_reduced_compressed</wcseo:eoId>
<wcseo:packageFormat>application/zip</wcseo:packageFormat>
</wcseo:GetEOCoverageSet>"""
return (params, "xml")
26 changes: 12 additions & 14 deletions eoxserver/services/ows/wcs/v20/geteocoverageset.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
from eoxserver.render.coverage import objects
from eoxserver.resources.coverages import models
from eoxserver.services.ows.wcs.v20.util import (
nsmap, parse_subset_kvp, parse_subset_xml, parse_scaleaxis_kvp,
nsmapGetEoCoverageSet, parse_subset_kvp, parse_subset_xml, parse_scaleaxis_kvp,
parse_scaleaxis_xml, parse_scaleextent_kvp, parse_scaleextent_xml,
parse_scalesize_kvp, parse_scalesize_xml, parse_interpolation
)
Expand Down Expand Up @@ -391,26 +391,24 @@ class WCS20GetEOCoverageSetKVPDecoder(kvp.Decoder):
interpolation = kvp.Parameter("interpolation", type=parse_interpolation, num="?")
subsettingcrs = kvp.Parameter("subsettingcrs", num="?")
outputcrs = kvp.Parameter("outputcrs", num="?")
interpolation = kvp.Parameter("interpolation", type=parse_interpolation, num="?")


class WCS20GetEOCoverageSetXMLDecoder(xml.Decoder):
eo_ids = xml.Parameter("wcseo11:eoId/text()", num="+", locator="eoid")
subsets = xml.Parameter("wcs:DimensionTrim", type=parse_subset_xml, num="*")
containment = xml.Parameter("wcseo11:containment/text()", type=containment_enum, locator="containment")
containment = xml.Parameter("wcseo11:containment/text()", num="?", type=containment_enum, locator="containment")
count = xml.Parameter("@count", type=pos_int, num="?", default=MAXSIZE, locator="count")
start_index = xml.Parameter("@startIndex", type=pos_int, num="?", default=0, locator="startIndex")
package_format = xml.Parameter("wcseo11:packageFormat/text()", type=parse_package_format, num="?", locator="packageFormat")
mediatype = xml.Parameter("wcs:mediaType/text()", num="?", locator="mediatype")
mediatype = xml.Parameter("wcseo11:mediaType/text()", num="?", locator="mediatype")
format = xml.Parameter("wcseo11:format/text()", num="?", locator="format")
apply_subset = xml.Parameter("wcseo11:applySubset/text()", type=parse_apply_subset, num="?", locator="format")
scalefactor = xml.Parameter("scal:ScaleByFactor/scal:scaleFactor/text()", type=float, num="?", locator="scalefactor")
scaleaxes = xml.Parameter("scal:ScaleByAxesFactor/scal:ScaleAxis", type=parse_scaleaxis_xml, num="*", default=(), locator="scaleaxes")
scalesize = xml.Parameter("scal:ScaleToSize/scal:TargetAxisSize", type=parse_scalesize_xml, num="*", default=(), locator="scalesize")
scaleextent = xml.Parameter("scal:ScaleToExtent/scal:TargetAxisExtent", type=parse_scaleextent_xml, num="*", default=(), locator="scaleextent")
interpolation = xml.Parameter("int:Interpolation/int:globalInterpolation/text()", type=parse_interpolation, num="?", locator="interpolation")
subsettingcrs = xml.Parameter("crs:subsettingCrs/text()", num="?", locator="subsettingcrs")
outputcrs = xml.Parameter("crs:outputCrs/text()", num="?", locator="outputcrs")
interpolation = xml.Parameter("int:Interpolation/int:globalInterpolation/text()", type=parse_interpolation, num="?", locator="interpolation")

namespaces = nsmap
scalefactor = xml.Parameter("wcs:Extension/scal:ScaleByFactor/scal:scaleFactor/text()", type=float, num="?", locator="scalefactor")
scaleaxes = xml.Parameter("wcs:Extension/scal:ScaleByAxesFactor/scal:ScaleAxis", type=parse_scaleaxis_xml, num="*", default=(), locator="scaleaxes")
scalesize = xml.Parameter("wcs:Extension/scal:ScaleToSize/scal:TargetAxisSize", type=parse_scalesize_xml, num="*", default=(), locator="scalesize")
scaleextent = xml.Parameter("wcs:Extension/scal:ScaleToExtent/scal:TargetAxisExtent", type=parse_scaleextent_xml, num="*", default=(), locator="scaleextent")
interpolation = xml.Parameter("wcs:Extension/int:Interpolation/int:globalInterpolation/text()", type=parse_interpolation, num="?", locator="interpolation")
subsettingcrs = xml.Parameter("wcs:Extension/crs:subsettingCrs/text()", num="?", locator="subsettingcrs")
outputcrs = xml.Parameter("wcs:Extension/crs:outputCrs/text()", num="?", locator="outputcrs")

namespaces = nsmapGetEoCoverageSet
5 changes: 4 additions & 1 deletion eoxserver/services/ows/wcs/v20/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@
# namespace map
nsmap = NameSpaceMap(
ns_xlink, ns_ogc, ns_ows, ns_gml, ns_gmlcov, ns_wcs, ns_crs, ns_rsub,
ns_eowcs, ns_om, ns_eop, ns_swe, ns_int, ns_scal
ns_eowcs, ns_om, ns_eop, ns_swe, ns_int, ns_scal,
)
nsmapGetEoCoverageSet = NameSpaceMap(
ns_wcs, ns_crs, ns_int, ns_scal, ns_wcseo11
)

# Element factories
Expand Down

0 comments on commit a325b28

Please sign in to comment.