Skip to content

Commit

Permalink
Fix unit tests
Browse files Browse the repository at this point in the history
- QgsFeature owns QgsFields (otherwise the assigned QgsFields may get deleted)
- updated QgsRenderChecker to use map settings + map renderer job
- fixed DPI issue in map renderer to map settings conversion
- fixed vector layer cache (failing file operations)

There are still few tests that keep failing compared to master branch,
but the reason for failure are tiny pixel diffs and we should probably just
update the expected images.
  • Loading branch information
wonder-sk committed Dec 11, 2013
1 parent 151bad5 commit 90b10f7
Show file tree
Hide file tree
Showing 13 changed files with 110 additions and 77 deletions.
3 changes: 2 additions & 1 deletion python/core/qgsrenderchecker.sip
Expand Up @@ -32,7 +32,8 @@ class QgsRenderChecker
QString imageToHash( QString theImageFile ); QString imageToHash( QString theImageFile );


void setRenderedImage( QString theImageFileName ); void setRenderedImage( QString theImageFileName );
void setMapRenderer( QgsMapRenderer * thepMapRenderer ); void setMapRenderer( QgsMapRenderer * thepMapRenderer ) /Deprecated/;
void setMapSettings( const QgsMapSettings& mapSettings );
bool runTest( QString theTestName, unsigned int theMismatchCount = 0 ); bool runTest( QString theTestName, unsigned int theMismatchCount = 0 );


bool compareImages( QString theTestName, unsigned int theMismatchCount = 0, QString theRenderedImageFile = "" ); bool compareImages( QString theTestName, unsigned int theMismatchCount = 0, QString theRenderedImageFile = "" );
Expand Down
12 changes: 4 additions & 8 deletions src/core/qgsfeature.cpp
Expand Up @@ -29,7 +29,6 @@ QgsFeature::QgsFeature( QgsFeatureId id )
, mGeometry( 0 ) , mGeometry( 0 )
, mOwnsGeometry( 0 ) , mOwnsGeometry( 0 )
, mValid( false ) , mValid( false )
, mFields( 0 )
{ {
// NOOP // NOOP
} }
Expand All @@ -39,7 +38,7 @@ QgsFeature::QgsFeature( const QgsFields &fields, QgsFeatureId id )
, mGeometry( 0 ) , mGeometry( 0 )
, mOwnsGeometry( 0 ) , mOwnsGeometry( 0 )
, mValid( false ) , mValid( false )
, mFields( &fields ) , mFields( fields )
{ {
initAttributes( fields.count() ); initAttributes( fields.count() );
} }
Expand Down Expand Up @@ -161,7 +160,7 @@ void QgsFeature::setGeometryAndOwnership( unsigned char *geom, size_t length )


void QgsFeature::setFields( const QgsFields* fields, bool init ) void QgsFeature::setFields( const QgsFields* fields, bool init )
{ {
mFields = fields; mFields = *fields;
if ( init ) if ( init )
{ {
initAttributes( fields->count() ); initAttributes( fields->count() );
Expand Down Expand Up @@ -239,12 +238,9 @@ QVariant QgsFeature::attribute( const QString& name ) const


int QgsFeature::fieldNameIndex( const QString& fieldName ) const int QgsFeature::fieldNameIndex( const QString& fieldName ) const
{ {
if ( !mFields ) for ( int i = 0; i < mFields.count(); ++i )
return -1;

for ( int i = 0; i < mFields->count(); ++i )
{ {
if ( QString::compare( mFields->at( i ).name(), fieldName, Qt::CaseInsensitive ) == 0 ) if ( QString::compare( mFields.at( i ).name(), fieldName, Qt::CaseInsensitive ) == 0 )
{ {
return i; return i;
} }
Expand Down
12 changes: 8 additions & 4 deletions src/core/qgsfeature.h
Expand Up @@ -102,7 +102,7 @@ typedef QVector<QVariant> QgsAttributes;
class QgsField; class QgsField;
typedef QMap<int, QgsField> QgsFieldMap; typedef QMap<int, QgsField> QgsFieldMap;



#include "qgsfield.h"




/** \ingroup core /** \ingroup core
Expand Down Expand Up @@ -221,13 +221,17 @@ class CORE_EXPORT QgsFeature
* C++: Defaults to false * C++: Defaults to false
* Python: Defaults to true * Python: Defaults to true
* @note added in 2.0 * @note added in 2.0
*
* TODO: QGIS3 - take reference, not pointer
*/ */
void setFields( const QgsFields* fields, bool initAttributes = false ); void setFields( const QgsFields* fields, bool initAttributes = false );


/** Get associated field map. may be NULL /** Get associated field map.
* @note added in 2.0 * @note added in 2.0
*
* TODO: QGIS 3 - return reference or value, not pointer
*/ */
const QgsFields* fields() const { return mFields; } const QgsFields* fields() const { return &mFields; }


/** Insert a value into attribute. Returns false if attribute name could not be converted to index. /** Insert a value into attribute. Returns false if attribute name could not be converted to index.
* Field map must be associated to make this work. * Field map must be associated to make this work.
Expand Down Expand Up @@ -308,7 +312,7 @@ class CORE_EXPORT QgsFeature
bool mValid; bool mValid;


//! Optional field map for name-based attribute lookups //! Optional field map for name-based attribute lookups
const QgsFields* mFields; QgsFields mFields;


}; // class QgsFeature }; // class QgsFeature


Expand Down
4 changes: 3 additions & 1 deletion src/core/qgsmaprenderer.cpp
Expand Up @@ -1070,12 +1070,14 @@ QgsMapRenderer::BlendMode QgsMapRenderer::getBlendModeEnum( const QPainter::Comp
} }
} }


Q_GUI_EXPORT extern int qt_defaultDpiX();

const QgsMapSettings& QgsMapRenderer::mapSettings() const QgsMapSettings& QgsMapRenderer::mapSettings()
{ {
// make sure the settings object is up-to-date // make sure the settings object is up-to-date
mMapSettings.setExtent( extent() ); mMapSettings.setExtent( extent() );
mMapSettings.setOutputSize( outputSize() ); mMapSettings.setOutputSize( outputSize() );
mMapSettings.setOutputDpi( outputDpi() ); mMapSettings.setOutputDpi( outputDpi() != 0 ? outputDpi() : qt_defaultDpiX() );
mMapSettings.setLayers( layerSet() ); mMapSettings.setLayers( layerSet() );
mMapSettings.setCrsTransformEnabled( hasCrsTransformEnabled() ); mMapSettings.setCrsTransformEnabled( hasCrsTransformEnabled() );
mMapSettings.setDestinationCrs( destinationCrs() ); mMapSettings.setDestinationCrs( destinationCrs() );
Expand Down
52 changes: 32 additions & 20 deletions src/core/qgsrenderchecker.cpp
Expand Up @@ -14,7 +14,9 @@
***************************************************************************/ ***************************************************************************/


#include "qgsrenderchecker.h" #include "qgsrenderchecker.h"

#include "qgis.h" #include "qgis.h"
#include "qgsmaprendererjob.h"


#include <QColor> #include <QColor>
#include <QPainter> #include <QPainter>
Expand All @@ -33,7 +35,6 @@ QgsRenderChecker::QgsRenderChecker( ) :
mMatchTarget( 0 ), mMatchTarget( 0 ),
mElapsedTime( 0 ), mElapsedTime( 0 ),
mElapsedTimeTarget( 0 ), mElapsedTimeTarget( 0 ),
mpMapRenderer( NULL ),
mControlPathPrefix( "" ) mControlPathPrefix( "" )
{ {


Expand Down Expand Up @@ -67,6 +68,16 @@ QString QgsRenderChecker::imageToHash( QString theImageFile )
return myHash.result().toHex().constData(); return myHash.result().toHex().constData();
} }


void QgsRenderChecker::setMapRenderer( QgsMapRenderer* thepMapRenderer )
{
mMapSettings = thepMapRenderer->mapSettings();
}

void QgsRenderChecker::setMapSettings( const QgsMapSettings& mapSettings )
{
mMapSettings = mapSettings;
}

bool QgsRenderChecker::isKnownAnomaly( QString theDiffImageFile ) bool QgsRenderChecker::isKnownAnomaly( QString theDiffImageFile )
{ {
QString myControlImageDir = controlImagePath() + mControlName QString myControlImageDir = controlImagePath() + mControlName
Expand Down Expand Up @@ -138,44 +149,45 @@ bool QgsRenderChecker::runTest( QString theTestName,
// //
// Now render our layers onto a pixmap // Now render our layers onto a pixmap
// //
QImage myImage( myExpectedImage.width(), mMapSettings.setBackgroundColor( qRgb( 152, 219, 249 ) );
myExpectedImage.height(), mMapSettings.setFlag( QgsMapSettings::Antialiasing );
QImage::Format_RGB32 ); mMapSettings.setOutputSize( QSize( myExpectedImage.width(), myExpectedImage.height() ) );
myImage.setDotsPerMeterX( myExpectedImage.dotsPerMeterX() );
myImage.setDotsPerMeterY( myExpectedImage.dotsPerMeterY() );
myImage.fill( qRgb( 152, 219, 249 ) );
QPainter myPainter( &myImage );
myPainter.setRenderHint( QPainter::Antialiasing );
mpMapRenderer->setOutputSize( QSize(
myExpectedImage.width(),
myExpectedImage.height() ),
myExpectedImage.logicalDpiX() );
QTime myTime; QTime myTime;
myTime.start(); myTime.start();
mpMapRenderer->render( &myPainter );
QgsMapRendererSequentialJob job( mMapSettings );
job.start();
job.waitForFinished();

mElapsedTime = myTime.elapsed(); mElapsedTime = myTime.elapsed();
myPainter.end();
QImage myImage = job.renderedImage();

// //
// Save the pixmap to disk so the user can make a // Save the pixmap to disk so the user can make a
// visual assessment if needed // visual assessment if needed
// //
mRenderedImageFile = QDir::tempPath() + QDir::separator() + mRenderedImageFile = QDir::tempPath() + QDir::separator() +
theTestName + "_result.png"; theTestName + "_result.png";

myImage.setDotsPerMeterX( myExpectedImage.dotsPerMeterX() );
myImage.setDotsPerMeterY( myExpectedImage.dotsPerMeterY() );
myImage.save( mRenderedImageFile, "PNG", 100 ); myImage.save( mRenderedImageFile, "PNG", 100 );


//create a world file to go with the image... //create a world file to go with the image...


QFile wldFile( QDir::tempPath() + QDir::separator() + theTestName + "_result.wld" ); QFile wldFile( QDir::tempPath() + QDir::separator() + theTestName + "_result.wld" );
if ( wldFile.open( QIODevice::WriteOnly ) ) if ( wldFile.open( QIODevice::WriteOnly ) )
{ {
QgsRectangle r = mpMapRenderer->extent(); QgsRectangle r = mMapSettings.extent();


QTextStream stream( &wldFile ); QTextStream stream( &wldFile );
stream << QString( "%1\r\n0 \r\n0 \r\n%2\r\n%3\r\n%4\r\n" ) stream << QString( "%1\r\n0 \r\n0 \r\n%2\r\n%3\r\n%4\r\n" )
.arg( qgsDoubleToString( mpMapRenderer->mapUnitsPerPixel() ) ) .arg( qgsDoubleToString( mMapSettings.mapUnitsPerPixel() ) )
.arg( qgsDoubleToString( -mpMapRenderer->mapUnitsPerPixel() ) ) .arg( qgsDoubleToString( -mMapSettings.mapUnitsPerPixel() ) )
.arg( qgsDoubleToString( r.xMinimum() + mpMapRenderer->mapUnitsPerPixel() / 2.0 ) ) .arg( qgsDoubleToString( r.xMinimum() + mMapSettings.mapUnitsPerPixel() / 2.0 ) )
.arg( qgsDoubleToString( r.yMaximum() - mpMapRenderer->mapUnitsPerPixel() / 2.0 ) ); .arg( qgsDoubleToString( r.yMaximum() - mMapSettings.mapUnitsPerPixel() / 2.0 ) );
} }


return compareImages( theTestName, theMismatchCount ); return compareImages( theTestName, theMismatchCount );
Expand Down
10 changes: 8 additions & 2 deletions src/core/qgsrenderchecker.h
Expand Up @@ -24,6 +24,7 @@


#include <qgsmaprenderer.h> #include <qgsmaprenderer.h>
#include <qgslogger.h> #include <qgslogger.h>
#include <qgsmapsettings.h>


class QImage; class QImage;


Expand Down Expand Up @@ -67,7 +68,12 @@ class CORE_EXPORT QgsRenderChecker
QString imageToHash( QString theImageFile ); QString imageToHash( QString theImageFile );


void setRenderedImage( QString theImageFileName ) { mRenderedImageFile = theImageFileName; }; void setRenderedImage( QString theImageFileName ) { mRenderedImageFile = theImageFileName; };
void setMapRenderer( QgsMapRenderer * thepMapRenderer ) { mpMapRenderer = thepMapRenderer; }; //! @deprecated since 2.1 - use setMapSettings()
Q_DECL_DEPRECATED void setMapRenderer( QgsMapRenderer * thepMapRenderer );

//! @note added in 2.1
void setMapSettings( const QgsMapSettings& mapSettings );

/** /**
* Test using renderer to generate the image to be compared. * Test using renderer to generate the image to be compared.
* @param theTestName - to be used as the basis for writing a file to * @param theTestName - to be used as the basis for writing a file to
Expand Down Expand Up @@ -111,7 +117,7 @@ class CORE_EXPORT QgsRenderChecker
unsigned int mMatchTarget; unsigned int mMatchTarget;
int mElapsedTime; int mElapsedTime;
int mElapsedTimeTarget; int mElapsedTimeTarget;
QgsMapRenderer * mpMapRenderer; QgsMapSettings mMapSettings;
QString mControlPathPrefix; QString mControlPathPrefix;


}; // class QgsRenderChecker }; // class QgsRenderChecker
Expand Down
36 changes: 20 additions & 16 deletions tests/src/core/testqgsblendmodes.cpp
Expand Up @@ -21,7 +21,7 @@
#include <QPainter> #include <QPainter>


//qgis includes... //qgis includes...
#include <qgsmaprenderer.h> #include <qgsmapsettings.h>
#include <qgsmaplayer.h> #include <qgsmaplayer.h>
#include <qgsvectorlayer.h> #include <qgsvectorlayer.h>
#include <qgsapplication.h> #include <qgsapplication.h>
Expand Down Expand Up @@ -50,7 +50,7 @@ class TestQgsBlendModes: public QObject
void rasterBlending(); void rasterBlending();
private: private:
bool imageCheck( QString theType ); //as above bool imageCheck( QString theType ); //as above
QgsMapRenderer * mpMapRenderer; QgsMapSettings mMapSettings;
QgsMapLayer * mpPointsLayer; QgsMapLayer * mpPointsLayer;
QgsMapLayer * mpPolysLayer; QgsMapLayer * mpPolysLayer;
QgsVectorLayer * mpLinesLayer; QgsVectorLayer * mpLinesLayer;
Expand Down Expand Up @@ -109,8 +109,6 @@ void TestQgsBlendModes::initTestCase()
QList<QgsMapLayer *>() << mRasterLayer1 ); QList<QgsMapLayer *>() << mRasterLayer1 );
QgsMapLayerRegistry::instance()->addMapLayers( QgsMapLayerRegistry::instance()->addMapLayers(
QList<QgsMapLayer *>() << mRasterLayer2 ); QList<QgsMapLayer *>() << mRasterLayer2 );

mpMapRenderer = new QgsMapRenderer();
} }
void TestQgsBlendModes::cleanupTestCase() void TestQgsBlendModes::cleanupTestCase()
{ {
Expand All @@ -123,17 +121,19 @@ void TestQgsBlendModes::vectorBlending()
QStringList myLayers; QStringList myLayers;
myLayers << mpLinesLayer->id(); myLayers << mpLinesLayer->id();
myLayers << mpPolysLayer->id(); myLayers << mpPolysLayer->id();
mpMapRenderer->setLayerSet( myLayers ); mMapSettings.setLayers( myLayers );


//Set blending modes for both layers //Set blending modes for both layers
mpLinesLayer->setBlendMode( QPainter::CompositionMode_Difference ); mpLinesLayer->setBlendMode( QPainter::CompositionMode_Difference );
mpPolysLayer->setBlendMode( QPainter::CompositionMode_Difference ); mpPolysLayer->setBlendMode( QPainter::CompositionMode_Difference );
mpMapRenderer->setExtent( mpPointsLayer->extent() ); mMapSettings.setExtent( mpPointsLayer->extent() );
QVERIFY( imageCheck( "vector_blendmodes" ) ); bool res = imageCheck( "vector_blendmodes" );


//Reset layers //Reset layers
mpLinesLayer->setBlendMode( QPainter::CompositionMode_SourceOver ); mpLinesLayer->setBlendMode( QPainter::CompositionMode_SourceOver );
mpPolysLayer->setBlendMode( QPainter::CompositionMode_SourceOver ); mpPolysLayer->setBlendMode( QPainter::CompositionMode_SourceOver );

QVERIFY( res );
} }


void TestQgsBlendModes::featureBlending() void TestQgsBlendModes::featureBlending()
Expand All @@ -142,15 +142,17 @@ void TestQgsBlendModes::featureBlending()
QStringList myLayers; QStringList myLayers;
myLayers << mpLinesLayer->id(); myLayers << mpLinesLayer->id();
myLayers << mpPolysLayer->id(); myLayers << mpPolysLayer->id();
mpMapRenderer->setLayerSet( myLayers ); mMapSettings.setLayers( myLayers );


//Set feature blending modes for point layer //Set feature blending modes for point layer
mpLinesLayer->setFeatureBlendMode( QPainter::CompositionMode_Plus ); mpLinesLayer->setFeatureBlendMode( QPainter::CompositionMode_Plus );
mpMapRenderer->setExtent( mpPointsLayer->extent() ); mMapSettings.setExtent( mpPointsLayer->extent() );
QVERIFY( imageCheck( "vector_featureblendmodes" ) ); bool res = imageCheck( "vector_featureblendmodes" );


//Reset layers //Reset layers
mpLinesLayer->setFeatureBlendMode( QPainter::CompositionMode_SourceOver ); mpLinesLayer->setFeatureBlendMode( QPainter::CompositionMode_SourceOver );

QVERIFY( res );
} }


void TestQgsBlendModes::vectorLayerTransparency() void TestQgsBlendModes::vectorLayerTransparency()
Expand All @@ -159,15 +161,17 @@ void TestQgsBlendModes::vectorLayerTransparency()
QStringList myLayers; QStringList myLayers;
myLayers << mpLinesLayer->id(); myLayers << mpLinesLayer->id();
myLayers << mpPolysLayer->id(); myLayers << mpPolysLayer->id();
mpMapRenderer->setLayerSet( myLayers ); mMapSettings.setLayers( myLayers );


//Set feature blending modes for point layer //Set feature blending modes for point layer
mpLinesLayer->setLayerTransparency( 50 ); mpLinesLayer->setLayerTransparency( 50 );
mpMapRenderer->setExtent( mpPointsLayer->extent() ); mMapSettings.setExtent( mpPointsLayer->extent() );
QVERIFY( imageCheck( "vector_layertransparency" ) ); bool res = imageCheck( "vector_layertransparency" );


//Reset layers //Reset layers
mpLinesLayer->setLayerTransparency( 0 ); mpLinesLayer->setLayerTransparency( 0 );

QVERIFY( res );
} }


void TestQgsBlendModes::rasterBlending() void TestQgsBlendModes::rasterBlending()
Expand All @@ -176,8 +180,8 @@ void TestQgsBlendModes::rasterBlending()
QStringList myLayers; QStringList myLayers;
myLayers << mRasterLayer1->id(); myLayers << mRasterLayer1->id();
myLayers << mRasterLayer2->id(); myLayers << mRasterLayer2->id();
mpMapRenderer->setLayerSet( myLayers ); mMapSettings.setLayers( myLayers );
mpMapRenderer->setExtent( mRasterLayer1->extent() ); mMapSettings.setExtent( mRasterLayer1->extent() );


// set blending mode for top layer // set blending mode for top layer
mRasterLayer1->setBlendMode( QPainter::CompositionMode_Plus ); mRasterLayer1->setBlendMode( QPainter::CompositionMode_Plus );
Expand All @@ -194,7 +198,7 @@ bool TestQgsBlendModes::imageCheck( QString theTestType )
//ensure the rendered output matches our control image //ensure the rendered output matches our control image
QgsRenderChecker myChecker; QgsRenderChecker myChecker;
myChecker.setControlName( "expected_" + theTestType ); myChecker.setControlName( "expected_" + theTestType );
myChecker.setMapRenderer( mpMapRenderer ); myChecker.setMapSettings( mMapSettings );
bool myResultFlag = myChecker.runTest( theTestType ); bool myResultFlag = myChecker.runTest( theTestType );
return myResultFlag; return myResultFlag;
} }
Expand Down
3 changes: 2 additions & 1 deletion tests/src/core/testqgscomposerhtml.cpp
Expand Up @@ -34,11 +34,12 @@ class TestQgsComposerHtml: public QObject
void tableMultiFrame(); //tests multiframe capabilities of composer html void tableMultiFrame(); //tests multiframe capabilities of composer html
private: private:
QgsComposition* mComposition; QgsComposition* mComposition;
QgsMapSettings mMapSettings;
}; };


void TestQgsComposerHtml::initTestCase() void TestQgsComposerHtml::initTestCase()
{ {
mComposition = new QgsComposition( 0 ); mComposition = new QgsComposition( mMapSettings );
mComposition->setPaperSize( 297, 210 ); //A4 landscape mComposition->setPaperSize( 297, 210 ); //A4 landscape
} }


Expand Down
4 changes: 3 additions & 1 deletion tests/src/core/testqgscomposershapes.cpp
Expand Up @@ -19,6 +19,7 @@
#include "qgscomposition.h" #include "qgscomposition.h"
#include "qgscompositionchecker.h" #include "qgscompositionchecker.h"
#include "qgscomposershape.h" #include "qgscomposershape.h"
#include "qgsmapsettings.h"
#include <QObject> #include <QObject>
#include <QtTest> #include <QtTest>
#include <QColor> #include <QColor>
Expand All @@ -40,6 +41,7 @@ class TestQgsComposerShapes: public QObject
private: private:
QgsComposition* mComposition; QgsComposition* mComposition;
QgsComposerShape* mComposerShape; QgsComposerShape* mComposerShape;
QgsMapSettings mMapSettings;
}; };


void TestQgsComposerShapes::initTestCase() void TestQgsComposerShapes::initTestCase()
Expand All @@ -48,7 +50,7 @@ void TestQgsComposerShapes::initTestCase()
QgsApplication::initQgis(); QgsApplication::initQgis();


//create composition with two rectangles //create composition with two rectangles
mComposition = new QgsComposition( 0 ); mComposition = new QgsComposition( mMapSettings );
mComposition->setPaperSize( 297, 210 ); //A4 landscape mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerShape = new QgsComposerShape( 20, 20, 150, 100, mComposition ); mComposerShape = new QgsComposerShape( 20, 20, 150, 100, mComposition );
mComposerShape->setBackgroundColor( QColor::fromRgb( 255, 150, 0 ) ); mComposerShape->setBackgroundColor( QColor::fromRgb( 255, 150, 0 ) );
Expand Down

0 comments on commit 90b10f7

Please sign in to comment.