Copy cached min/max value to provider test suite

This commit is contained in:
Nyall Dawson 2018-05-15 07:55:57 +10:00
parent 9b28e3d7f5
commit 26174ea9ad
2 changed files with 109 additions and 25 deletions

View File

@ -9,6 +9,7 @@ the Free Software Foundation; either version 2 of the License, or
from builtins import str from builtins import str
from builtins import object from builtins import object
__author__ = 'Matthias Kuhn' __author__ = 'Matthias Kuhn'
__date__ = '2015-04-27' __date__ = '2015-04-27'
__copyright__ = 'Copyright 2015, The QGIS Project' __copyright__ = 'Copyright 2015, The QGIS Project'
@ -35,7 +36,6 @@ from featuresourcetestbase import FeatureSourceTestCase
class ProviderTestCase(FeatureSourceTestCase): class ProviderTestCase(FeatureSourceTestCase):
''' '''
This is a collection of tests for vector data providers and kept generic. This is a collection of tests for vector data providers and kept generic.
To make use of it, subclass it and set self.source to a provider you want to test. To make use of it, subclass it and set self.source to a provider you want to test.
@ -101,15 +101,33 @@ class ProviderTestCase(FeatureSourceTestCase):
self.assert_query(provider, 'ymax($geometry) > 80', [1, 2]) self.assert_query(provider, 'ymax($geometry) > 80', [1, 2])
self.assert_query(provider, 'area($geometry) > 10', [1]) self.assert_query(provider, 'area($geometry) > 10', [1])
self.assert_query(provider, 'perimeter($geometry) < 12', [2, 3]) self.assert_query(provider, 'perimeter($geometry) < 12', [2, 3])
self.assert_query(provider, 'relate($geometry,geom_from_wkt( \'Polygon ((-68.2 82.1, -66.95 82.1, -66.95 79.05, -68.2 79.05, -68.2 82.1))\')) = \'FF2FF1212\'', [1, 3]) self.assert_query(provider,
self.assert_query(provider, 'relate($geometry,geom_from_wkt( \'Polygon ((-68.2 82.1, -66.95 82.1, -66.95 79.05, -68.2 79.05, -68.2 82.1))\'), \'****F****\')', [1, 3]) 'relate($geometry,geom_from_wkt( \'Polygon ((-68.2 82.1, -66.95 82.1, -66.95 79.05, -68.2 79.05, -68.2 82.1))\')) = \'FF2FF1212\'',
self.assert_query(provider, 'crosses($geometry,geom_from_wkt( \'Linestring (-68.2 82.1, -66.95 82.1, -66.95 79.05)\'))', [2]) [1, 3])
self.assert_query(provider, 'overlaps($geometry,geom_from_wkt( \'Polygon ((-68.2 82.1, -66.95 82.1, -66.95 79.05, -68.2 79.05, -68.2 82.1))\'))', [2]) self.assert_query(provider,
self.assert_query(provider, 'within($geometry,geom_from_wkt( \'Polygon ((-75.1 76.1, -75.1 81.6, -68.8 81.6, -68.8 76.1, -75.1 76.1))\'))', [1]) 'relate($geometry,geom_from_wkt( \'Polygon ((-68.2 82.1, -66.95 82.1, -66.95 79.05, -68.2 79.05, -68.2 82.1))\'), \'****F****\')',
self.assert_query(provider, 'overlaps(translate($geometry,-1,-1),geom_from_wkt( \'Polygon ((-75.1 76.1, -75.1 81.6, -68.8 81.6, -68.8 76.1, -75.1 76.1))\'))', [1]) [1, 3])
self.assert_query(provider, 'overlaps(buffer($geometry,1),geom_from_wkt( \'Polygon ((-75.1 76.1, -75.1 81.6, -68.8 81.6, -68.8 76.1, -75.1 76.1))\'))', [1, 3]) self.assert_query(provider,
self.assert_query(provider, 'intersects(centroid($geometry),geom_from_wkt( \'Polygon ((-74.4 78.2, -74.4 79.1, -66.8 79.1, -66.8 78.2, -74.4 78.2))\'))', [2]) 'crosses($geometry,geom_from_wkt( \'Linestring (-68.2 82.1, -66.95 82.1, -66.95 79.05)\'))',
self.assert_query(provider, 'intersects(point_on_surface($geometry),geom_from_wkt( \'Polygon ((-74.4 78.2, -74.4 79.1, -66.8 79.1, -66.8 78.2, -74.4 78.2))\'))', [1, 2]) [2])
self.assert_query(provider,
'overlaps($geometry,geom_from_wkt( \'Polygon ((-68.2 82.1, -66.95 82.1, -66.95 79.05, -68.2 79.05, -68.2 82.1))\'))',
[2])
self.assert_query(provider,
'within($geometry,geom_from_wkt( \'Polygon ((-75.1 76.1, -75.1 81.6, -68.8 81.6, -68.8 76.1, -75.1 76.1))\'))',
[1])
self.assert_query(provider,
'overlaps(translate($geometry,-1,-1),geom_from_wkt( \'Polygon ((-75.1 76.1, -75.1 81.6, -68.8 81.6, -68.8 76.1, -75.1 76.1))\'))',
[1])
self.assert_query(provider,
'overlaps(buffer($geometry,1),geom_from_wkt( \'Polygon ((-75.1 76.1, -75.1 81.6, -68.8 81.6, -68.8 76.1, -75.1 76.1))\'))',
[1, 3])
self.assert_query(provider,
'intersects(centroid($geometry),geom_from_wkt( \'Polygon ((-74.4 78.2, -74.4 79.1, -66.8 79.1, -66.8 78.2, -74.4 78.2))\'))',
[2])
self.assert_query(provider,
'intersects(point_on_surface($geometry),geom_from_wkt( \'Polygon ((-74.4 78.2, -74.4 79.1, -66.8 79.1, -66.8 78.2, -74.4 78.2))\'))',
[1, 2])
self.assert_query(provider, 'distance($geometry,geom_from_wkt( \'Point (-70 70)\')) > 7', [1, 2]) self.assert_query(provider, 'distance($geometry,geom_from_wkt( \'Point (-70 70)\')) > 7', [1, 2])
def testGetFeaturesUncompiled(self): def testGetFeaturesUncompiled(self):
@ -145,7 +163,8 @@ class ProviderTestCase(FeatureSourceTestCase):
self.source.setSubsetString(None) self.source.setSubsetString(None)
expected = set([2, 3, 4]) expected = set([2, 3, 4])
assert set(expected) == result, 'Expected {} and got {} when testing subset string {}'.format(set(expected), result, subset) assert set(expected) == result, 'Expected {} and got {} when testing subset string {}'.format(set(expected),
result, subset)
self.assertTrue(all_valid) self.assertTrue(all_valid)
# Subset string AND filter rect # Subset string AND filter rect
@ -156,7 +175,8 @@ class ProviderTestCase(FeatureSourceTestCase):
all_valid = (all(f.isValid() for f in self.source.getFeatures(request))) all_valid = (all(f.isValid() for f in self.source.getFeatures(request)))
self.source.setSubsetString(None) self.source.setSubsetString(None)
expected = set([2]) expected = set([2])
assert set(expected) == result, 'Expected {} and got {} when testing subset string {}'.format(set(expected), result, subset) assert set(expected) == result, 'Expected {} and got {} when testing subset string {}'.format(set(expected),
result, subset)
self.assertTrue(all_valid) self.assertTrue(all_valid)
# Subset string AND filter rect, version 2 # Subset string AND filter rect, version 2
@ -165,7 +185,8 @@ class ProviderTestCase(FeatureSourceTestCase):
result = set([f['pk'] for f in self.source.getFeatures(QgsFeatureRequest().setFilterRect(extent))]) result = set([f['pk'] for f in self.source.getFeatures(QgsFeatureRequest().setFilterRect(extent))])
self.source.setSubsetString(None) self.source.setSubsetString(None)
expected = set([2, 4]) expected = set([2, 4])
assert set(expected) == result, 'Expected {} and got {} when testing subset string {}'.format(set(expected), result, subset) assert set(expected) == result, 'Expected {} and got {} when testing subset string {}'.format(set(expected),
result, subset)
# Subset string AND expression # Subset string AND expression
self.source.setSubsetString(subset) self.source.setSubsetString(subset)
@ -174,7 +195,8 @@ class ProviderTestCase(FeatureSourceTestCase):
all_valid = (all(f.isValid() for f in self.source.getFeatures(request))) all_valid = (all(f.isValid() for f in self.source.getFeatures(request)))
self.source.setSubsetString(None) self.source.setSubsetString(None)
expected = set([2, 4]) expected = set([2, 4])
assert set(expected) == result, 'Expected {} and got {} when testing subset string {}'.format(set(expected), result, subset) assert set(expected) == result, 'Expected {} and got {} when testing subset string {}'.format(set(expected),
result, subset)
self.assertTrue(all_valid) self.assertTrue(all_valid)
def getSubsetString(self): def getSubsetString(self):
@ -330,8 +352,11 @@ class ProviderTestCase(FeatureSourceTestCase):
self.assertTrue(provider_extent.isNull()) self.assertTrue(provider_extent.isNull())
def testUnique(self): def testUnique(self):
self.assertEqual(set(self.source.uniqueValues(self.source.fields().lookupField('cnt'))), set([-200, 100, 200, 300, 400])) self.assertEqual(set(self.source.uniqueValues(self.source.fields().lookupField('cnt'))),
assert set(['Apple', 'Honey', 'Orange', 'Pear', NULL]) == set(self.source.uniqueValues(self.source.fields().lookupField('name'))), 'Got {}'.format(set(self.source.uniqueValues(self.source.fields().lookupField('name')))) set([-200, 100, 200, 300, 400]))
assert set(['Apple', 'Honey', 'Orange', 'Pear', NULL]) == set(
self.source.uniqueValues(self.source.fields().lookupField('name'))), 'Got {}'.format(
set(self.source.uniqueValues(self.source.fields().lookupField('name'))))
if self.source.supportsSubsetString(): if self.source.supportsSubsetString():
subset = self.getSubsetString2() subset = self.getSubsetString2()
@ -352,7 +377,8 @@ class ProviderTestCase(FeatureSourceTestCase):
self.assertEqual(len(result), 2) self.assertEqual(len(result), 2)
self.assertTrue(result.issubset(set(['Pear', 'Orange', 'Apple']))) self.assertTrue(result.issubset(set(['Pear', 'Orange', 'Apple'])))
assert set([u'Apple', u'Honey', u'Orange', u'Pear', NULL]) == set(self.source.uniqueValues(field_index)), 'Got {}'.format(set(self.source.uniqueValues(field_index))) assert set([u'Apple', u'Honey', u'Orange', u'Pear', NULL]) == set(
self.source.uniqueValues(field_index)), 'Got {}'.format(set(self.source.uniqueValues(field_index)))
if self.source.supportsSubsetString(): if self.source.supportsSubsetString():
subset = self.getSubsetString2() subset = self.getSubsetString2()
@ -425,7 +451,8 @@ class ProviderTestCase(FeatureSourceTestCase):
else: else:
# expect fail # expect fail
self.assertFalse(l.dataProvider().addFeatures([f1, f2]), 'Provider reported no AddFeatures capability, but returned true to addFeatures') self.assertFalse(l.dataProvider().addFeatures([f1, f2]),
'Provider reported no AddFeatures capability, but returned true to addFeatures')
def testAddFeatureFastInsert(self): def testAddFeatureFastInsert(self):
if not getattr(self, 'getEditableLayer', None): if not getattr(self, 'getEditableLayer', None):
@ -465,7 +492,8 @@ class ProviderTestCase(FeatureSourceTestCase):
f2.setAttributes([7, 330]) f2.setAttributes([7, 330])
result, added = l.dataProvider().addFeatures([f1, f2]) result, added = l.dataProvider().addFeatures([f1, f2])
self.assertTrue(result, 'Provider returned False to addFeatures with missing attributes. Providers should accept these features but add NULL attributes to the end of the existing attributes to the required field length.') self.assertTrue(result,
'Provider returned False to addFeatures with missing attributes. Providers should accept these features but add NULL attributes to the end of the existing attributes to the required field length.')
f1.setId(added[0].id()) f1.setId(added[0].id())
f2.setId(added[1].id()) f2.setId(added[1].id())
@ -519,7 +547,8 @@ class ProviderTestCase(FeatureSourceTestCase):
f2.setAttributes([8]) f2.setAttributes([8])
result, added = l.dataProvider().addFeatures([f1, f2]) result, added = l.dataProvider().addFeatures([f1, f2])
self.assertFalse(result, 'Provider returned True to addFeatures with incorrect geometry type. Providers should reject these features.') self.assertFalse(result,
'Provider returned True to addFeatures with incorrect geometry type. Providers should reject these features.')
# make sure feature was not added # make sure feature was not added
added = [f for f in l.dataProvider().getFeatures() if f['pk'] == 7] added = [f for f in l.dataProvider().getFeatures() if f['pk'] == 7]
@ -610,7 +639,8 @@ class ProviderTestCase(FeatureSourceTestCase):
if l.dataProvider().capabilities() & QgsVectorDataProvider.FastTruncate or l.dataProvider().capabilities() & QgsVectorDataProvider.DeleteFeatures: if l.dataProvider().capabilities() & QgsVectorDataProvider.FastTruncate or l.dataProvider().capabilities() & QgsVectorDataProvider.DeleteFeatures:
# expect success # expect success
result = l.dataProvider().truncate() result = l.dataProvider().truncate()
self.assertTrue(result, 'Provider reported FastTruncate or DeleteFeatures capability, but returned False to truncate()') self.assertTrue(result,
'Provider reported FastTruncate or DeleteFeatures capability, but returned False to truncate()')
# check result # check result
features = [f['pk'] for f in l.dataProvider().getFeatures()] features = [f['pk'] for f in l.dataProvider().getFeatures()]
@ -640,7 +670,8 @@ class ProviderTestCase(FeatureSourceTestCase):
if l.dataProvider().capabilities() & QgsVectorDataProvider.ChangeAttributeValues: if l.dataProvider().capabilities() & QgsVectorDataProvider.ChangeAttributeValues:
# expect success # expect success
result = l.dataProvider().changeAttributeValues(changes) result = l.dataProvider().changeAttributeValues(changes)
self.assertTrue(result, 'Provider reported ChangeAttributeValues capability, but returned False to changeAttributeValues') self.assertTrue(result,
'Provider reported ChangeAttributeValues capability, but returned False to changeAttributeValues')
# check result # check result
self.testGetFeatures(l.dataProvider(), changed_attributes=new_attr_map) self.testGetFeatures(l.dataProvider(), changed_attributes=new_attr_map)
@ -733,3 +764,56 @@ class ProviderTestCase(FeatureSourceTestCase):
# expect fail # expect fail
self.assertFalse(l.dataProvider().changeFeatures(attribute_changes, geometry_changes), self.assertFalse(l.dataProvider().changeFeatures(attribute_changes, geometry_changes),
'Provider reported no ChangeAttributeValues capability, but returned true to changeFeatures') 'Provider reported no ChangeAttributeValues capability, but returned true to changeFeatures')
def testMinMaxAfterChanges(self):
"""
Tests retrieving field min and max value after making changes to the provider's features
"""
if not getattr(self, 'getEditableLayer', None):
return
vl = self.getEditableLayer()
self.assertTrue(vl.isValid())
self.assertEqual(vl.dataProvider().minimumValue(0), 1)
self.assertEqual(vl.dataProvider().minimumValue(1), -200)
self.assertEqual(vl.dataProvider().maximumValue(0), 5)
self.assertEqual(vl.dataProvider().maximumValue(1), 400)
# add feature
f6 = QgsFeature()
f6.setAttributes([15, 1400])
res, [f6] = vl.dataProvider().addFeatures([f6])
self.assertTrue(res)
self.assertEqual(vl.dataProvider().minimumValue(0), 1)
self.assertEqual(vl.dataProvider().minimumValue(1), -200)
self.assertEqual(vl.dataProvider().maximumValue(0), 15)
self.assertEqual(vl.dataProvider().maximumValue(1), 1400)
f7 = QgsFeature()
f7.setAttributes([0, -1400])
res, [f7] = vl.dataProvider().addFeatures([f7])
self.assertTrue(res)
self.assertEqual(vl.dataProvider().minimumValue(0), 0)
self.assertEqual(vl.dataProvider().minimumValue(1), -1400)
self.assertEqual(vl.dataProvider().maximumValue(0), 15)
self.assertEqual(vl.dataProvider().maximumValue(1), 1400)
# change attribute values
self.assertTrue(vl.dataProvider().changeAttributeValues({f6.id(): {1: 150}, f7.id(): {1: -100}}))
self.assertEqual(vl.dataProvider().minimumValue(1), -200)
self.assertEqual(vl.dataProvider().maximumValue(1), 400)
# delete features
f1 = [f for f in vl.getFeatures() if f['pk'] == 5][0]
f3 = [f for f in vl.getFeatures() if f['pk'] == 3][0]
self.assertTrue(vl.dataProvider().deleteFeatures([f6.id(), f7.id()]))
self.assertEqual(vl.dataProvider().minimumValue(0), 1)
self.assertEqual(vl.dataProvider().minimumValue(1), -200)
self.assertEqual(vl.dataProvider().maximumValue(0), 5)
self.assertEqual(vl.dataProvider().maximumValue(1), 400)
if vl.dataProvider().capabilities() & QgsVectorDataProvider.DeleteAttributes:
# delete attributes
self.assertTrue(vl.dataProvider().deleteAttributes([0]))
self.assertEqual(vl.dataProvider().minimumValue(0), -200)
self.assertEqual(vl.dataProvider().maximumValue(0), 400)

Binary file not shown.