1 /***************************************************************************
2     testmaprendererjob.cpp
3     ---------------------
4     begin                : November 2013
5     copyright            : (C) 2013 by Martin Dobias
6     email                : wonder dot sk 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 
16 #include "qgstest.h"
17 #include <QObject>
18 
19 #include "qgsapplication.h"
20 #include "qgsproject.h"
21 #include "qgsmaprenderercache.h"
22 #include "qgsmaprendererjob.h"
23 #include "qgsvectorlayer.h"
24 
25 class TestQgsMapRendererJob : public QObject
26 {
27     Q_OBJECT
28   private slots:
29     void initTestCase();// will be called before the first testfunction is executed.
30     void cleanupTestCase();// will be called after the last testfunction was executed.
31 
32     void testNormal();
33 
34     void testTwoTimes();
35 
36     void testCancelWithoutStart();
37     void testWaitWithoutStart();
38     void testCancelFinished();
39     void testStartWhileRunning();
40     void testDestructWhileRunning();
41 
42     void testErrors();
43 
44     void testCache();
45 
46   private:
47     QStringList mLayerIds;
48 };
49 
_loadLayer(QString path)50 static QString _loadLayer( QString path )
51 {
52   QgsMapLayer *layer = new QgsVectorLayer( path, "testlayer", "ogr" );
53   QVERIFY( layer->isValid() );
54   QgsProject::instance()->addMapLayer( layer );
55   return layer->id();
56 }
57 
_mapSettings(QStringList layerIds)58 static QgsMapSettings _mapSettings( QStringList layerIds )
59 {
60   QgsMapSettings settings;
61   settings.setLayers( layerIds );
62   settings.setExtent( settings.fullExtent() );
63   settings.setOutputSize( QSize( 512, 512 ) );
64   return settings;
65 }
66 
67 
initTestCase()68 void TestQgsMapRendererJob::initTestCase()
69 {
70   QgsApplication::init();
71   QgsApplication::initQgis();
72 
73   mLayerIds << _loadLayer( "/data/gis/sas/trans-trail-l.dbf" );
74   mLayerIds << _loadLayer( "/data/gis/sas/bnd-ocean-a.shp" );
75   mLayerIds << _loadLayer( "/data/gis/sas/bnd-political-boundary-a.shp" );
76 
77 }
78 
cleanupTestCase()79 void TestQgsMapRendererJob::cleanupTestCase()
80 {
81   QgsApplication::exitQgis();
82 }
83 
testNormal()84 void TestQgsMapRendererJob::testNormal()
85 {
86   QgsMapSettings settings( _mapSettings( mLayerIds ) );
87 
88   QImage imgS, imgP;
89 
90   QgsMapRendererSequentialJob jobS( settings );
91   QCOMPARE( jobS.isActive(), false );
92   jobS.start();
93   QCOMPARE( jobS.isActive(), true );
94   jobS.waitForFinished();
95   QCOMPARE( jobS.isActive(), false );
96   imgS = jobS.renderedImage();
97 
98   //
99 
100   QgsMapRendererParallelJob jobP( settings );
101   QCOMPARE( jobP.isActive(), false );
102   jobP.start();
103   QCOMPARE( jobP.isActive(), true );
104   jobP.waitForFinished();
105   QCOMPARE( jobP.isActive(), false );
106   imgP = jobP.renderedImage();
107 
108   // TODO: custom painter
109 
110   imgS.save( QDir::tempPath() + "/imgS.png" );
111   imgP.save( QDir::tempPath() + "/imgP.png" );
112   //img.save( QDir::tempPath() + "/img5.png");
113 
114   QCOMPARE( imgS, imgP );
115 }
116 
testTwoTimes()117 void TestQgsMapRendererJob::testTwoTimes()
118 {
119   QgsMapSettings settings( _mapSettings( mLayerIds ) );
120 
121   QgsMapRendererSequentialJob job( settings );
122   job.start();
123   job.waitForFinished();
124 
125   QImage img1 = job.renderedImage();
126 
127   job.start();
128   job.waitForFinished();
129 
130   QImage img2 = job.renderedImage();
131 
132   QVERIFY( img1 == img2 );
133 
134   //
135 
136   QgsMapRendererParallelJob jobP( settings );
137   jobP.start();
138   jobP.waitForFinished();
139 
140   QImage img3 = jobP.renderedImage();
141 
142   jobP.start();
143   jobP.waitForFinished();
144 
145   QImage img4 = jobP.renderedImage();
146 
147   QVERIFY( img3 == img4 );
148 }
149 
150 
testCancelWithoutStart()151 void TestQgsMapRendererJob::testCancelWithoutStart()
152 {
153   QgsMapSettings settings( _mapSettings( mLayerIds ) );
154 
155   QgsMapRendererSequentialJob job( settings );
156   job.cancel();
157 
158   //
159 
160   QgsMapRendererParallelJob jobP( settings );
161   jobP.cancel();
162 }
163 
testWaitWithoutStart()164 void TestQgsMapRendererJob::testWaitWithoutStart()
165 {
166   QgsMapSettings settings( _mapSettings( mLayerIds ) );
167 
168   QgsMapRendererSequentialJob job( settings );
169   job.waitForFinished();
170 
171   //
172 
173   QgsMapRendererParallelJob jobP( settings );
174   jobP.waitForFinished();
175 }
176 
testCancelFinished()177 void TestQgsMapRendererJob::testCancelFinished()
178 {
179   QgsMapSettings settings( _mapSettings( mLayerIds ) );
180 
181   QgsMapRendererSequentialJob job( settings );
182   job.start();
183   job.waitForFinished();
184   job.cancel();
185 
186   //
187 
188   QgsMapRendererParallelJob jobP( settings );
189   jobP.start();
190   jobP.waitForFinished();
191   jobP.cancel();
192 }
193 
testStartWhileRunning()194 void TestQgsMapRendererJob::testStartWhileRunning()
195 {
196   QgsMapSettings settings( _mapSettings( mLayerIds ) );
197 
198   QgsMapRendererSequentialJob job( settings );
199   job.start();
200   job.start();
201   job.waitForFinished();
202 
203   //
204 
205   QgsMapRendererParallelJob jobP( settings );
206   jobP.start();
207   jobP.start();
208   jobP.waitForFinished();
209 }
210 
testDestructWhileRunning()211 void TestQgsMapRendererJob::testDestructWhileRunning()
212 {
213   QgsMapSettings settings( _mapSettings( mLayerIds ) );
214 
215   QgsMapRendererSequentialJob job( settings );
216   job.start();
217 
218   //
219 
220   QgsMapRendererParallelJob jobP( settings );
221   jobP.start();
222 }
223 
testErrors()224 void TestQgsMapRendererJob::testErrors()
225 {
226   QgsVectorLayer *l = new QgsVectorLayer( "/data/gis/sas/trans-trail-l.dbf", "test", "ogr" );
227   QVERIFY( l->isValid() );
228   QgsProject::instance()->addMapLayer( l );
229   QgsMapSettings settings( _mapSettings( QStringList( l->id() ) ) );
230 
231   l->setRenderer( nullptr ); // this has to produce an error
232 
233   QgsMapRendererSequentialJob job( settings );
234   job.start();
235   job.waitForFinished();
236 
237   QCOMPARE( job.errors().count(), 1 );
238   QCOMPARE( job.errors()[0].layerID, l->id() );
239 
240   QgsProject::instance()->removeMapLayer( l->id() );
241 
242   QString fakeLayerID = "non-existing layer ID";
243   QgsMapSettings settings2( _mapSettings( QStringList( fakeLayerID ) ) );
244 
245   QgsMapRendererSequentialJob job2( settings2 );
246   job2.start();
247   job2.waitForFinished();
248 
249   QCOMPARE( job2.errors().count(), 1 );
250   QCOMPARE( job2.errors()[0].layerID, fakeLayerID );
251 }
252 
testCache()253 void TestQgsMapRendererJob::testCache()
254 {
255   QgsVectorLayer *l = new QgsVectorLayer( "/data/gis/sas/trans-trail-l.dbf", "test", "ogr" );
256   QVERIFY( l->isValid() );
257   QgsProject::instance()->addMapLayer( l );
258   QgsMapSettings settings( _mapSettings( QStringList( l->id() ) ) );
259 
260   QgsMapRendererCache cache;
261 
262   QgsMapRendererSequentialJob job( settings );
263   job.setCache( &cache );
264 
265   QTime t;
266   t.start();
267   job.start();
268   job.waitForFinished();
269   int timeNotCachedMS = t.elapsed();
270 
271   QImage i1 = job.renderedImage();
272 
273   QgsMapRendererSequentialJob job2( settings );
274   job2.setCache( &cache );
275 
276   t.start();
277   job2.start();
278   job2.waitForFinished();
279   int timeCachedMS = t.elapsed();
280 
281   QImage i2 = job2.renderedImage();
282 
283   QCOMPARE( i1, i2 );
284   QVERIFY( timeNotCachedMS > 100 );
285   QVERIFY( timeCachedMS < 10 );
286   qDebug( "CACHING %d vs %d (ms)", timeNotCachedMS, timeCachedMS );
287 
288   QgsProject::instance()->removeMapLayer( l->id() );
289 }
290 
291 
292 QGSTEST_MAIN( TestQgsMapRendererJob )
293 #include "testmaprendererjob.moc"
294