14
14
15
15
import os
16
16
import shutil
17
+ import sys
17
18
import tempfile
18
19
19
20
from qgis .core import QgsVectorLayer , QgsVectorDataProvider , QgsWKBTypes
@@ -34,6 +35,21 @@ def GDAL_COMPUTE_VERSION(maj, min, rev):
34
35
# Note - doesn't implement ProviderTestCase as most OGR provider is tested by the shapefile provider test
35
36
36
37
38
+ def count_opened_filedescriptors (filename_to_test ):
39
+ count = - 1
40
+ if sys .platform .startswith ('linux' ):
41
+ count = 0
42
+ open_files_dirname = '/proc/%d/fd' % os .getpid ()
43
+ filenames = os .listdir (open_files_dirname )
44
+ for filename in filenames :
45
+ full_filename = open_files_dirname + '/' + filename
46
+ if os .path .exists (full_filename ):
47
+ link = os .readlink (full_filename )
48
+ if os .path .basename (link ) == os .path .basename (filename_to_test ):
49
+ count += 1
50
+ return count
51
+
52
+
37
53
class PyQgsOGRProvider (unittest .TestCase ):
38
54
39
55
@classmethod
@@ -134,6 +150,76 @@ def testGpxElevation(self):
134
150
self .assertEqual (f .constGeometry ().geometry ().pointN (1 ).z (), 2 )
135
151
self .assertEqual (f .constGeometry ().geometry ().pointN (2 ).z (), 3 )
136
152
153
+ def testNoDanglingFileDescriptorAfterCloseVariant1 (self ):
154
+ ''' Test that when closing the provider all file handles are released '''
155
+
156
+ datasource = os .path .join (self .basetestpath , 'testNoDanglingFileDescriptorAfterCloseVariant1.csv' )
157
+ with open (datasource , 'wt' ) as f :
158
+ f .write ('id,WKT\n ' )
159
+ f .write ('1,\n ' )
160
+ f .write ('2,POINT(2 49)\n ' )
161
+
162
+ vl = QgsVectorLayer (u'{}|layerid=0' .format (datasource ), u'test' , u'ogr' )
163
+ self .assertTrue (vl .isValid ())
164
+ # The iterator will take one extra connection
165
+ myiter = vl .getFeatures ()
166
+ # Consume one feature but the iterator is still opened
167
+ f = next (myiter )
168
+ self .assertTrue (f .isValid ())
169
+
170
+ if sys .platform .startswith ('linux' ):
171
+ self .assertEqual (count_opened_filedescriptors (datasource ), 2 )
172
+
173
+ # Should release one file descriptor
174
+ del vl
175
+
176
+ # Non portable, but Windows testing is done with trying to unlink
177
+ if sys .platform .startswith ('linux' ):
178
+ self .assertEqual (count_opened_filedescriptors (datasource ), 1 )
179
+
180
+ f = next (myiter )
181
+ self .assertTrue (f .isValid ())
182
+
183
+ # Should release one file descriptor
184
+ del myiter
185
+
186
+ # Non portable, but Windows testing is done with trying to unlink
187
+ if sys .platform .startswith ('linux' ):
188
+ self .assertEqual (count_opened_filedescriptors (datasource ), 0 )
189
+
190
+ # Check that deletion works well (can only fail on Windows)
191
+ os .unlink (datasource )
192
+ self .assertFalse (os .path .exists (datasource ))
193
+
194
+ def testNoDanglingFileDescriptorAfterCloseVariant2 (self ):
195
+ ''' Test that when closing the provider all file handles are released '''
196
+
197
+ datasource = os .path .join (self .basetestpath , 'testNoDanglingFileDescriptorAfterCloseVariant2.csv' )
198
+ with open (datasource , 'wt' ) as f :
199
+ f .write ('id,WKT\n ' )
200
+ f .write ('1,\n ' )
201
+ f .write ('2,POINT(2 49)\n ' )
202
+
203
+ vl = QgsVectorLayer (u'{}|layerid=0' .format (datasource ), u'test' , u'ogr' )
204
+ self .assertTrue (vl .isValid ())
205
+ # Consume all features.
206
+ myiter = vl .getFeatures ()
207
+ for feature in myiter :
208
+ pass
209
+ # The iterator is closed, but the corresponding connection still not closed
210
+ if sys .platform .startswith ('linux' ):
211
+ self .assertEqual (count_opened_filedescriptors (datasource ), 2 )
212
+
213
+ # Should release one file descriptor
214
+ del vl
215
+
216
+ # Non portable, but Windows testing is done with trying to unlink
217
+ if sys .platform .startswith ('linux' ):
218
+ self .assertEqual (count_opened_filedescriptors (datasource ), 0 )
219
+
220
+ # Check that deletion works well (can only fail on Windows)
221
+ os .unlink (datasource )
222
+ self .assertFalse (os .path .exists (datasource ))
137
223
138
224
if __name__ == '__main__' :
139
225
unittest .main ()
0 commit comments