Skip to content

Commit 5d84b26

Browse files
committedJul 18, 2012
wcs test unit
1 parent 37ab951 commit 5d84b26

File tree

7 files changed

+451
-11
lines changed

7 files changed

+451
-11
lines changed
 

‎src/providers/wcs/qgswcscapabilities.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,6 @@ bool QgsWcsCapabilities::describeCoverage( QString const &identifier, bool force
282282
return false;
283283
}
284284

285-
QgsDebugMsg( "supportedFormat = " + coverage->supportedFormat.join( "," ) );
286-
287285
return true;
288286
}
289287

@@ -696,13 +694,13 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
696694
// requestResponseCRSs and requestCRSs + responseCRSs are alternatives
697695
coverage->supportedCrs = domElementsTexts( coverageOfferingElement, "supportedCRSs.requestResponseCRSs" );
698696
// TODO: requestCRSs, responseCRSs - must be then implemented also in provider
699-
QgsDebugMsg( "supportedCrs = " + coverage->supportedCrs.join( "," ) );
697+
//QgsDebugMsg( "supportedCrs = " + coverage->supportedCrs.join( "," ) );
700698

701699
coverage->nativeCrs = domElementText( coverageOfferingElement, "supportedCRSs.nativeCRSs" );
702700

703701
// may be GTiff, GeoTIFF, TIFF, GIF, ....
704702
coverage->supportedFormat = domElementsTexts( coverageOfferingElement, "supportedFormats.formats" );
705-
QgsDebugMsg( "supportedFormat = " + coverage->supportedFormat.join( "," ) );
703+
//QgsDebugMsg( "supportedFormat = " + coverage->supportedFormat.join( "," ) );
706704

707705
// spatialDomain and Grid/RectifiedGrid are optional according to specificationi.
708706
// If missing, we cannot get native resolution and size.
@@ -775,6 +773,18 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
775773
}
776774
}
777775

776+
// NULL / no data values
777+
// TODO: handle multiple range sets
778+
foreach( QString text, domElementsTexts( coverageOfferingElement, "rangeSet.RangeSet.nullValue.singleValue" ) )
779+
{
780+
bool ok;
781+
double val = text.toDouble( &ok );
782+
if ( ok )
783+
{
784+
coverage->nullValues.append( val );
785+
}
786+
}
787+
778788
coverage->described = true;
779789

780790
return true;
@@ -848,6 +858,18 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom11( QByteArray const &xml, QgsW
848858
// if urn:ogc:def:crs:OGC::imageCRS BoundingBox was not found
849859
}
850860

861+
// NULL / no data values
862+
// TODO: handle multiple fields / ranges (?)
863+
foreach( QString text, domElementsTexts( docElem, "CoverageDescription.Range.Field.NullValue" ) )
864+
{
865+
bool ok;
866+
double val = text.toDouble( &ok );
867+
if ( ok )
868+
{
869+
coverage->nullValues.append( val );
870+
}
871+
}
872+
851873
coverage->described = true;
852874

853875
return true;
@@ -894,7 +916,7 @@ void QgsWcsCapabilities::parseCoverageSummary( QDomElement const & e, QgsWcsCove
894916
}
895917
n1 = n1.nextSibling();
896918
}
897-
QgsDebugMsg( "supportedFormat = " + coverageSummary.supportedFormat.join( "," ) );
919+
//QgsDebugMsg( "supportedFormat = " + coverageSummary.supportedFormat.join( "," ) );
898920

899921
// We collected params to be inherited, do children
900922
n1 = e.firstChild();
@@ -998,12 +1020,10 @@ void QgsWcsCapabilities::showMessageBox( const QString& title, const QString& te
9981020
QgsWcsCoverageSummary QgsWcsCapabilities::coverage( QString const & theIdentifier )
9991021
{
10001022
QgsWcsCoverageSummary * cp = coverageSummary( theIdentifier );
1001-
QgsDebugMsg( "supportedFormat = " + ( *cp ).supportedFormat.join( "," ) );
10021023
if ( cp ) return *cp;
10031024

10041025
QgsWcsCoverageSummary c;
10051026
initCoverageSummary( c );
1006-
QgsDebugMsg( "supportedFormat = " + c.supportedFormat.join( "," ) );
10071027
return c;
10081028
}
10091029

‎src/providers/wcs/qgswcscapabilities.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct QgsWcsCoverageSummary
4343
QString abstract;
4444
QStringList supportedCrs;
4545
QStringList supportedFormat;
46+
QList<double> nullValues;
4647
QgsRectangle wgs84BoundingBox; // almost useless, we need the native
4748
QString nativeCrs;
4849
// Map of bounding boxes, key is CRS name (srsName), e.g. EPSG:4326

‎src/providers/wcs/qgswcsprovider.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
9494

9595
mValid = false;
9696

97-
parseUri( uri );
97+
if ( !parseUri( uri ) ) return;
9898

9999
// GetCapabilities and DescribeCoverage
100100
// TODO(?): do only DescribeCoverage to avoid one request
@@ -125,6 +125,22 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
125125
return;
126126
}
127127

128+
// It may happen that format is empty (e.g. uri created in python script),
129+
// in that casei select one from available formats
130+
if ( mFormat.isEmpty() )
131+
{
132+
// TIFF is known by GDAL
133+
mFormat = mCoverageSummary.supportedFormat.filter( "tif", Qt::CaseInsensitive ).value( 0 );
134+
}
135+
if ( mFormat.isEmpty() )
136+
{
137+
// Take the first if TIFF was not found
138+
mFormat = mCoverageSummary.supportedFormat.value( 0 );
139+
}
140+
141+
// We cannot continue without format, it is required
142+
if ( mFormat.isEmpty() ) return;
143+
128144
// It could happen (usually not with current QgsWCSSourceSelect if at least
129145
// one CRS is available) that crs is not set in uri, in that case we
130146
// use the native, if available, or the first supported
@@ -218,6 +234,7 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
218234
GDALRasterBandH gdalBand = GDALGetRasterBand( mCachedGdalDataset, i );
219235
GDALDataType myGdalDataType = GDALGetRasterDataType( gdalBand );
220236

237+
QgsDebugMsg( QString( "myGdalDataType[%1] = %2" ).arg( i - 1 ).arg( myGdalDataType ) );
221238
mSrcGdalDataType.append( myGdalDataType );
222239
// TODO: This could be shared with GDAL provider
223240
int isValid = false;
@@ -269,6 +286,13 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
269286
}
270287
}
271288
mNoDataValue.append( myNoDataValue );
289+
290+
// TODO: what to do if null values from DescribeCoverage differ?
291+
if ( !mCoverageSummary.nullValues.contains( myNoDataValue ) )
292+
{
293+
QgsDebugMsg( QString( "noDataValue %1 is missing in nullValues from CoverageDescription" ).arg( myNoDataValue ) );
294+
}
295+
272296
mValidNoDataValue = true;
273297

274298
QgsDebugMsg( QString( "mSrcGdalDataType[%1] = %2" ).arg( i - 1 ).arg( mSrcGdalDataType[i-1] ) );
@@ -298,7 +322,7 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
298322
QgsDebugMsg( "Constructed ok, provider valid." );
299323
}
300324

301-
void QgsWcsProvider::parseUri( QString uriString )
325+
bool QgsWcsProvider::parseUri( QString uriString )
302326
{
303327

304328
QgsDebugMsg( "uriString = " + uriString );
@@ -326,8 +350,11 @@ void QgsWcsProvider::parseUri( QString uriString )
326350

327351
setFormat( uri.param( "format" ) );
328352

353+
// TODO: if not defined, use the best available, probably EPSG:4326
329354
setCoverageCrs( uri.param( "crs" ) );
330355
mCrs.createFromOgcWmsCrs( uri.param( "crs" ) );
356+
357+
return true;
331358
}
332359

333360
QString QgsWcsProvider::prepareUri( QString uri ) const

‎src/providers/wcs/qgswcsprovider.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,9 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
214214
*
215215
* \param uri uri to check
216216
*
217-
* \note added in 1.1
218217
*/
219218

220-
void parseUri( QString uri );
219+
bool parseUri( QString uri );
221220

222221
/**
223222
* \brief Prepare the URI so that we can later simply append param=value

‎tests/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ IF (ENABLE_TESTS)
22
ADD_SUBDIRECTORY(core)
33
ADD_SUBDIRECTORY(gui)
44
ADD_SUBDIRECTORY(analysis)
5+
ADD_SUBDIRECTORY(providers)
56
ENDIF (ENABLE_TESTS)

‎tests/src/providers/CMakeLists.txt

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Standard includes and utils to compile into all tests.
2+
3+
#####################################################
4+
# Don't forget to include output directory, otherwise
5+
# the UI file won't be wrapped!
6+
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
7+
${CMAKE_CURRENT_BINARY_DIR}
8+
${CMAKE_SOURCE_DIR}/src/core
9+
${CMAKE_SOURCE_DIR}/src/core/raster
10+
${QT_INCLUDE_DIR}
11+
${GDAL_INCLUDE_DIR}
12+
${PROJ_INCLUDE_DIR}
13+
${GEOS_INCLUDE_DIR}
14+
)
15+
16+
#############################################################
17+
# Compiler defines
18+
19+
# This define is used for tests that need to locate the test
20+
# data under tests/testdata in the qgis source tree.
21+
# the TEST_DATA_DIR variable is set in the top level CMakeLists.txt
22+
ADD_DEFINITIONS(-DTEST_DATA_DIR="\\"${TEST_DATA_DIR}\\"")
23+
24+
ADD_DEFINITIONS(-DINSTALL_PREFIX="\\"${CMAKE_INSTALL_PREFIX}\\"")
25+
#############################################################
26+
# libraries
27+
28+
# because of htonl
29+
IF (WIN32)
30+
SET(PLATFORM_LIBRARIES wsock32)
31+
ENDIF (WIN32)
32+
33+
# Since the tests are not actually installed, but rather
34+
# run directly from the build/src/tests dir we need to
35+
# ensure the qgis libs can be found.
36+
IF (APPLE)
37+
# For Mac OS X, the executable must be at the root of the bundle's executable folder
38+
SET (CMAKE_INSTALL_NAME_DIR @executable_path/../../../src/core)
39+
ENDIF (APPLE)
40+
41+
#note for tests we should not include the moc of our
42+
#qtests in the executable file list as the moc is
43+
#directly included in the sources
44+
#and should not be compiled twice. Trying to include
45+
#them in will cause an error at build time
46+
47+
#No relinking and full RPATH for the install tree
48+
#See: http://www.cmake.org/Wiki/CMake_RPATH_handling#No_relinking_and_full_RPATH_for_the_install_tree
49+
50+
MACRO (ADD_QGIS_TEST testname testsrc)
51+
SET(qgis_${testname}_SRCS ${testsrc} ${util_SRCS})
52+
SET(qgis_${testname}_MOC_CPPS ${testsrc})
53+
QT4_WRAP_CPP(qgis_${testname}_MOC_SRCS ${qgis_${testname}_MOC_CPPS})
54+
ADD_CUSTOM_TARGET(qgis_${testname}moc ALL DEPENDS ${qgis_${testname}_MOC_SRCS})
55+
ADD_EXECUTABLE(qgis_${testname} ${qgis_${testname}_SRCS})
56+
ADD_DEPENDENCIES(qgis_${testname} qgis_${testname}moc)
57+
TARGET_LINK_LIBRARIES(qgis_${testname}
58+
${QT_QTXML_LIBRARY}
59+
${QT_QTCORE_LIBRARY}
60+
${QT_QTSVG_LIBRARY}
61+
${QT_QTTEST_LIBRARY}
62+
${PROJ_LIBRARY}
63+
${GEOS_LIBRARY}
64+
${GDAL_LIBRARY}
65+
qgis_core)
66+
ADD_TEST(qgis_${testname} ${CMAKE_CURRENT_BINARY_DIR}/../../../output/bin/qgis_${testname})
67+
ENDMACRO (ADD_QGIS_TEST)
68+
69+
#############################################################
70+
# Tests:
71+
72+
ADD_QGIS_TEST(wcsprovidertest testqgswcsprovider.cpp)
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
/***************************************************************************
2+
testqgswcsprovider.cpp
3+
--------------------------------------
4+
Date : July 2012
5+
Copyright : (C) 2012 by Radim Blazek
6+
Email : radim dot blazek at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
#include <cmath>
16+
17+
#include <QtTest>
18+
#include <QObject>
19+
#include <QString>
20+
#include <QStringList>
21+
#include <QObject>
22+
#include <QApplication>
23+
24+
#include <qgsdatasourceuri.h>
25+
#include <qgsrasterlayer.h>
26+
#include <qgsrasterdataprovider.h>
27+
#include <qgsproviderregistry.h>
28+
#include <qgsapplication.h>
29+
30+
#define TINY_VALUE std::numeric_limits<double>::epsilon() * 20
31+
32+
/** \ingroup UnitTests
33+
* This is a unit test for the QgsRasterLayer class.
34+
*/
35+
class TestQgsWcsProvider: public QObject
36+
{
37+
Q_OBJECT;
38+
private slots:
39+
void initTestCase();// will be called before the first testfunction is executed.
40+
void cleanupTestCase();// will be called after the last testfunction was executed.
41+
void init() {};// will be called before each testfunction is executed.
42+
void cleanup() {};// will be called after every testfunction.
43+
44+
void read();
45+
private:
46+
bool read( QString identifier, QString theFilePath, QString & theReport );
47+
// Log error in html
48+
void error( QString theMessage, QString &theReport );
49+
// compare values and add table row in html report, set ok to false if not equal
50+
QString compareHead();
51+
void compare( QString theParamName, int wcsVal, int gdalVal, QString &theReport, bool &theOk );
52+
void compare( QString theParamName, double wcsVal, double gdalVal, QString &theReport, bool &theOk, double theTolerance = 0 );
53+
void compareRow( QString theParamName, QString wcsVal, QString gdalVal, QString &theReport, bool theOk, QString theDifference = "", QString theTolerance = "" );
54+
double tolerance( double val, int places = 6 );
55+
QString mTestDataDir;
56+
QString mReport;
57+
QString mUrl;
58+
};
59+
60+
//runs before all tests
61+
void TestQgsWcsProvider::initTestCase()
62+
{
63+
// init QGIS's paths - true means that all path will be inited from prefix
64+
QgsApplication::init( QString() );
65+
QgsApplication::initQgis();
66+
QString mySettings = QgsApplication::showSettings();
67+
mySettings = mySettings.replace( "\n", "<br />" );
68+
mReport += "<h1>WCS provider tests</h1>\n";
69+
mReport += "<p>" + mySettings + "</p>";
70+
71+
mReport += "<style>";
72+
mReport += ".tab { border-spacing: 0px; border-width: 1px 1px 0 0; border-style: solid; }";
73+
mReport += ".cell { border-width: 0 0 1px 1px; border-style: solid; font-size: smaller; text-align: center}";
74+
mReport += ".ok { background: #00ff00; }";
75+
mReport += ".err { background: #ff0000; }";
76+
mReport += ".errmsg { color: #ff0000; }";
77+
mReport += "</style>";
78+
79+
80+
//create some objects that will be used in all tests...
81+
//create a raster layer that will be used in all tests...
82+
mTestDataDir = QString( TEST_DATA_DIR ) + QDir::separator() + "raster";
83+
qDebug() << "mTestDataDir = " << mTestDataDir;
84+
85+
mUrl = "http://127.0.0.1//cgi-bin/wcstest";
86+
}
87+
88+
//runs after all tests
89+
void TestQgsWcsProvider::cleanupTestCase()
90+
{
91+
QString myReportFile = QDir::tempPath() + QDir::separator() + "qgiswcstest.html";
92+
QFile myFile( myReportFile );
93+
//if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
94+
if ( myFile.open( QIODevice::WriteOnly ) )
95+
{
96+
QTextStream myQTextStream( &myFile );
97+
myQTextStream << mReport;
98+
myFile.close();
99+
}
100+
}
101+
102+
void TestQgsWcsProvider::read( )
103+
{
104+
bool ok = true;
105+
QStringList identifiers;
106+
107+
// identifiers in mapfile have the same name as files without .tif extension
108+
identifiers << "band1_byte_noct_epsg4326";
109+
identifiers << "band1_int16_noct_epsg4326";
110+
identifiers << "band1_float32_noct_epsg4326";
111+
112+
// How to reasonably log multiple fails within this loop?
113+
foreach( QString identifier, identifiers )
114+
{
115+
QString filePath = mTestDataDir + QDir::separator() + identifier + ".tif";
116+
if ( !read( identifier, filePath, mReport ) )
117+
{
118+
ok = false;
119+
}
120+
}
121+
QVERIFY2( ok, "Reading data failed. See report for details." );
122+
}
123+
124+
bool TestQgsWcsProvider::read( QString theIdentifier, QString theFilePath, QString & theReport )
125+
{
126+
bool ok = true;
127+
QgsDataSourceURI uri;
128+
uri.setParam( "url", mUrl );
129+
uri.setParam( "identifier", theIdentifier );
130+
uri.setParam( "crs", "epsg:4326" );
131+
132+
theReport += QString( "<h2>Identifier (coverage): %1</h2>" ).arg( theIdentifier );
133+
134+
QgsRasterDataProvider* wcsProvider = QgsRasterLayer::loadProvider( "wcs", uri.encodedUri() );
135+
if ( !wcsProvider || !wcsProvider->isValid() )
136+
{
137+
error( QString( "Cannot load WCS provider with URI: %1" ).arg( QString( uri.encodedUri() ) ), theReport );
138+
ok = false;
139+
}
140+
141+
QgsRasterDataProvider* gdalProvider = QgsRasterLayer::loadProvider( "gdal", theFilePath );
142+
if ( !gdalProvider || !gdalProvider->isValid() )
143+
{
144+
error( QString( "Cannot load GDAL provider with URI: %1" ).arg( theFilePath ), theReport );
145+
ok = false;
146+
}
147+
148+
if ( !ok ) return false;
149+
150+
theReport += QString( "WCS URI: %1<br>" ).arg( QString( uri.encodedUri() ).replace( "&", "&amp;" ) );
151+
theReport += QString( "GDAL URI: %1<br>" ).arg( theFilePath );
152+
153+
theReport += "<br>";
154+
theReport += "<table class='tab'>";
155+
theReport += compareHead();
156+
157+
compare( "Band count", wcsProvider->bandCount(), gdalProvider->bandCount(), theReport, ok );
158+
159+
compare( "Width", wcsProvider->xSize(), gdalProvider->xSize(), theReport, ok );
160+
compare( "Height", wcsProvider->ySize(), gdalProvider->ySize(), theReport, ok );
161+
162+
compareRow( "Extent", wcsProvider->extent().toString(), gdalProvider->extent().toString(), theReport, wcsProvider->extent() == gdalProvider->extent() );
163+
if ( wcsProvider->extent() != gdalProvider->extent() ) ok = false;
164+
165+
if ( !ok ) return false;
166+
167+
compare( "No data (NULL) value", wcsProvider->noDataValue(), gdalProvider->noDataValue(), theReport, ok );
168+
169+
theReport += "</table>";
170+
171+
172+
bool allOk = true;
173+
for ( int band = 1; band <= gdalProvider->bandCount(); band++ )
174+
{
175+
bool bandOk = true;
176+
theReport += QString( "<h3>Band %1</h3>" ).arg( band );
177+
theReport += "<table class='tab'>";
178+
theReport += compareHead();
179+
180+
// Data types may differ (?)
181+
bool typesOk = true;
182+
compare( "Source data type", wcsProvider->srcDataType( band ), gdalProvider->srcDataType( band ), theReport, typesOk );
183+
compare( "Data type", wcsProvider->dataType( band ), gdalProvider->dataType( band ), theReport, typesOk ) ;
184+
185+
bool statsOk = true;
186+
QgsRasterBandStats wcsStats = wcsProvider->bandStatistics( band );
187+
QgsRasterBandStats gdalStats = gdalProvider->bandStatistics( band );
188+
189+
// Min/max may 'slightly' differ, for big numbers however, the difference may
190+
// be quite big, for example for Float32 with max -3.332e+38, the difference is 1.47338e+24
191+
double tol = tolerance( gdalStats.minimumValue );
192+
compare( "Minimum value", wcsStats.minimumValue, gdalStats.minimumValue, theReport, statsOk, tol );
193+
tol = tolerance( gdalStats.maximumValue );
194+
compare( "Maximum value", wcsStats.maximumValue, gdalStats.maximumValue, theReport, statsOk, tol );
195+
196+
// TODO: enable once fixed (WCS excludes nulls but GDAL does not)
197+
//compare( "Cells count", wcsStats.elementCount, gdalStats.elementCount, theReport, statsOk );
198+
199+
tol = tolerance( gdalStats.mean );
200+
compare( "Mean", wcsStats.mean, gdalStats.mean, theReport, statsOk, tol );
201+
202+
// stdDev usually differ significantly
203+
tol = tolerance( gdalStats.stdDev, 1 );
204+
compare( "Standard deviation", wcsStats.stdDev, gdalStats.stdDev, theReport, statsOk, tol );
205+
206+
theReport += "</table>";
207+
theReport += "<br>";
208+
209+
if ( !bandOk )
210+
{
211+
allOk = false;
212+
continue;
213+
}
214+
215+
if ( !statsOk || typesOk )
216+
{
217+
allOk = false;
218+
// create values table anyway so that values are available
219+
}
220+
221+
theReport += "<table><tr>";
222+
theReport += "<td>Data comparison</td>";
223+
theReport += "<td class='cell ok' style='border: 1px solid'>correct&nbsp;value</td>";
224+
theReport += "<td></td>";
225+
theReport += "<td class='cell err' style='border: 1px solid'>wrong&nbsp;value<br>expected value</td></tr>";
226+
theReport += "</tr></table>";
227+
theReport += "<br>";
228+
229+
int width = gdalProvider->xSize();
230+
int height = gdalProvider->ySize();
231+
int blockSize = width * height * gdalProvider->typeSize( gdalProvider->dataType( band ) ) ;
232+
void * gdalData = malloc( blockSize );
233+
void * wcsData = malloc( blockSize );
234+
235+
gdalProvider->readBlock( band, gdalProvider->extent(), width, height, gdalData );
236+
wcsProvider->readBlock( band, gdalProvider->extent(), width, height, wcsData );
237+
238+
// compare data values
239+
QString htmlTable = "<table class='tab'>";
240+
for ( int row = 0; row < height; row ++ )
241+
{
242+
htmlTable += "<tr>";
243+
for ( int col = 0; col < width; col ++ )
244+
{
245+
bool cellOk = true;
246+
double wcsVal = wcsProvider->readValue( wcsData, wcsProvider->dataType( band ), row * width + col );
247+
double gdalVal = gdalProvider->readValue( gdalData, gdalProvider->dataType( band ), row * width + col );
248+
249+
QString valStr;
250+
if ( wcsVal == gdalVal )
251+
{
252+
valStr = QString( "%1" ).arg( wcsVal );
253+
}
254+
else
255+
{
256+
cellOk = false;
257+
allOk = false;
258+
valStr = QString( "%1<br>%2" ).arg( wcsVal ).arg( gdalVal );
259+
}
260+
htmlTable += QString( "<td class='cell %1'>%2</td>" ).arg( cellOk ? "ok" : "err" ).arg( valStr );
261+
}
262+
htmlTable += "</tr>";
263+
}
264+
htmlTable += "</table>";
265+
266+
theReport += htmlTable;
267+
268+
free( gdalData );
269+
free( wcsData );
270+
}
271+
delete wcsProvider;
272+
delete gdalProvider;
273+
return allOk;
274+
}
275+
276+
void TestQgsWcsProvider::error( QString theMessage, QString &theReport )
277+
{
278+
theReport += "<font class='errmsg'>Error: ";
279+
theReport += theMessage;
280+
theReport += "</font>";
281+
}
282+
283+
double TestQgsWcsProvider::tolerance( double val, int places )
284+
{
285+
// float precission is about 7 decimal digits, double about 16
286+
// default places = 6
287+
return 1. * pow( 10, round( log10( qAbs( val ) ) - places ) );
288+
}
289+
290+
QString TestQgsWcsProvider::compareHead()
291+
{
292+
return "<tr><th class='cell'>Param name</th><th class='cell'>WCS (tested) value</th><th class='cell'>GDAL (expected) value</th><th class='cell'>Difference</th><th class='cell'>Tolerance</th></tr>";
293+
}
294+
295+
void TestQgsWcsProvider::compare( QString theParamName, int wcsVal, int gdalVal, QString &theReport, bool &theOk )
296+
{
297+
bool ok = wcsVal == gdalVal;
298+
compareRow( theParamName, QString::number( wcsVal ), QString::number( gdalVal ), theReport, ok, QString::number( wcsVal - gdalVal ) );
299+
if ( !ok ) theOk = false;
300+
}
301+
302+
void TestQgsWcsProvider::compare( QString theParamName, double wcsVal, double gdalVal, QString &theReport, bool &theOk, double theTolerance )
303+
{
304+
bool ok = ( qAbs( wcsVal - gdalVal ) <= theTolerance );
305+
306+
compareRow( theParamName, QString::number( wcsVal ), QString::number( gdalVal ), theReport, ok, QString::number( wcsVal - gdalVal ), QString::number( theTolerance ) );
307+
if ( !ok ) theOk = false;
308+
}
309+
310+
void TestQgsWcsProvider::compareRow( QString theParamName, QString wcsVal, QString gdalVal, QString &theReport, bool theOk, QString theDifference, QString theTolerance )
311+
{
312+
theReport += "<tr>";
313+
theReport += QString( "<td class='cell'>%1</td><td class='cell %2'>%3</td><td class='cell'>%4</td>" ).arg( theParamName ).arg( theOk ? "ok" : "err" ).arg( wcsVal ).arg( gdalVal );
314+
theReport += QString( "<td class='cell'>%1</td>" ).arg( theDifference );
315+
theReport += QString( "<td class='cell'>%1</td>" ).arg( theTolerance );
316+
theReport += "</tr>";
317+
}
318+
319+
QTEST_MAIN( TestQgsWcsProvider )
320+
#include "moc_testqgswcsprovider.cxx"

0 commit comments

Comments
 (0)
Please sign in to comment.