QGIS API Documentation 3.43.0-Master (3ee7834ace6)
qgstestutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgstestutils.cpp
3 --------------------
4 begin : January 2018
5 copyright : (C) 2018 by Nyall Dawson
6 email : nyall.dawson@gmail.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 "qgstestutils.h"
18#include "qgsconnectionpool.h"
19#include <QtConcurrentMap>
22
23static void getFeaturesForProvider( const QPair< std::shared_ptr< QgsAbstractFeatureSource >, QgsFeatureRequest > &pair )
24{
25 QgsFeatureIterator it = pair.first->getFeatures( pair.second );
26 QgsFeature f;
27 while ( it.nextFeature( f ) )
28 {
29
30 }
31}
32
33bool QgsTestUtils::testProviderIteratorThreadSafety( QgsVectorDataProvider *provider, const QgsFeatureRequest &request )
34{
35 constexpr int JOBS_TO_RUN = 100;
36 QList< QPair< std::shared_ptr< QgsAbstractFeatureSource >, QgsFeatureRequest > > jobs;
37 jobs.reserve( JOBS_TO_RUN );
38 for ( int i = 0; i < JOBS_TO_RUN; ++i )
39 {
40 jobs.append( qMakePair( std::shared_ptr< QgsAbstractFeatureSource >( provider->featureSource() ), request ) );
41 }
42
43 //freaking hammer the provider with a ton of concurrent requests.
44 //thread unsafe providers... you better be ready!!!!
45 QtConcurrent::blockingMap( jobs, getFeaturesForProvider );
46
47 return true;
48}
49
50bool QgsTestUtils::compareDomElements( const QDomElement &element1, const QDomElement &element2 )
51{
52 QString tag1 = element1.tagName();
53 tag1.replace( QRegularExpression( ".*:" ), QString() );
54 QString tag2 = element2.tagName();
55 tag2.replace( QRegularExpression( ".*:" ), QString() );
56 if ( tag1 != tag2 )
57 {
58 qDebug( "Different tag names: %s, %s", tag1.toLatin1().data(), tag2.toLatin1().data() );
59 return false;
60 }
61
62 if ( element1.hasAttributes() != element2.hasAttributes() )
63 {
64 qDebug( "Different hasAttributes: %s, %s", tag1.toLatin1().data(), tag2.toLatin1().data() );
65 return false;
66 }
67
68 if ( element1.hasAttributes() )
69 {
70 const QDomNamedNodeMap attrs1 = element1.attributes();
71 const QDomNamedNodeMap attrs2 = element2.attributes();
72
73 if ( attrs1.size() != attrs2.size() )
74 {
75 qDebug( "Different attributes size: %s, %s", tag1.toLatin1().data(), tag2.toLatin1().data() );
76 return false;
77 }
78
79 for ( int i = 0; i < attrs1.size(); ++i )
80 {
81 const QDomNode node1 = attrs1.item( i );
82 const QDomAttr attr1 = node1.toAttr();
83
84 if ( !element2.hasAttribute( attr1.name() ) )
85 {
86 qDebug( "Element2 has not attribute: %s, %s, %s", tag1.toLatin1().data(), tag2.toLatin1().data(), attr1.name().toLatin1().data() );
87 return false;
88 }
89
90 if ( element2.attribute( attr1.name() ) != attr1.value() )
91 {
92 qDebug( "Element2 attribute has not the same value: %s, %s, %s", tag1.toLatin1().data(), tag2.toLatin1().data(), attr1.name().toLatin1().data() );
93 return false;
94 }
95 }
96 }
97
98 if ( element1.hasChildNodes() != element2.hasChildNodes() )
99 {
100 qDebug( "Different childNodes: %s, %s", tag1.toLatin1().data(), tag2.toLatin1().data() );
101 return false;
102 }
103
104 if ( element1.hasChildNodes() )
105 {
106 const QDomNodeList nodes1 = element1.childNodes();
107 const QDomNodeList nodes2 = element2.childNodes();
108
109 if ( nodes1.size() != nodes2.size() )
110 {
111 qDebug( "Different childNodes size: %s, %s", tag1.toLatin1().data(), tag2.toLatin1().data() );
112 return false;
113 }
114
115 for ( int i = 0; i < nodes1.size(); ++i )
116 {
117 const QDomNode node1 = nodes1.at( i );
118 const QDomNode node2 = nodes2.at( i );
119 if ( node1.isElement() && node2.isElement() )
120 {
121 QDomElement elt1 = node1.toElement();
122 QDomElement elt2 = node2.toElement();
123
124 if ( !compareDomElements( elt1, elt2 ) )
125 return false;
126 }
127 else if ( node1.isText() && node2.isText() )
128 {
129 const QDomText txt1 = node1.toText();
130 const QDomText txt2 = node2.toText();
131
132 if ( txt1.data() != txt2.data() )
133 {
134 qDebug( "Different text data: %s %s", tag1.toLatin1().data(), txt1.data().toLatin1().data() );
135 qDebug( "Different text data: %s %s", tag2.toLatin1().data(), txt2.data().toLatin1().data() );
136 return false;
137 }
138 }
139 }
140 }
141
142 if ( element1.text() != element2.text() )
143 {
144 qDebug( "Different text: %s %s", tag1.toLatin1().data(), element1.text().toLatin1().data() );
145 qDebug( "Different text: %s %s", tag2.toLatin1().data(), element2.text().toLatin1().data() );
146 return false;
147 }
148
149 return true;
150}
151
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
This class wraps a request for features to a vector layer (or directly its vector data provider).
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
This is the base class for vector data providers.
virtual QgsAbstractFeatureSource * featureSource() const =0
Returns feature source object that can be used for querying provider's data.