Skip to content
Permalink
Browse files

Copy cached min/max value to provider test suite

  • Loading branch information
nyalldawson committed May 14, 2018
1 parent 9b28e3d commit 26174ea9adda06da5492237698fabe55d2a70b51
Showing with 109 additions and 25 deletions.
  1. +109 −25 tests/src/python/providertestbase.py
  2. BIN tests/testdata/provider/bug_17795.gpkg
@@ -9,6 +9,7 @@

from builtins import str
from builtins import object

__author__ = 'Matthias Kuhn'
__date__ = '2015-04-27'
__copyright__ = 'Copyright 2015, The QGIS Project'
@@ -35,7 +36,6 @@


class ProviderTestCase(FeatureSourceTestCase):

'''
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.
@@ -101,15 +101,33 @@ def runPolyGetFeatureTests(self, provider):
self.assert_query(provider, 'ymax($geometry) > 80', [1, 2])
self.assert_query(provider, 'area($geometry) > 10', [1])
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, '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])
self.assert_query(provider, 'crosses($geometry,geom_from_wkt( \'Linestring (-68.2 82.1, -66.95 82.1, -66.95 79.05)\'))', [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,
'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,
'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])
self.assert_query(provider,
'crosses($geometry,geom_from_wkt( \'Linestring (-68.2 82.1, -66.95 82.1, -66.95 79.05)\'))',
[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])

def testGetFeaturesUncompiled(self):
@@ -145,7 +163,8 @@ def testSubsetString(self):
self.source.setSubsetString(None)

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)

# Subset string AND filter rect
@@ -156,7 +175,8 @@ def testSubsetString(self):
all_valid = (all(f.isValid() for f in self.source.getFeatures(request)))
self.source.setSubsetString(None)
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)

# Subset string AND filter rect, version 2
@@ -165,7 +185,8 @@ def testSubsetString(self):
result = set([f['pk'] for f in self.source.getFeatures(QgsFeatureRequest().setFilterRect(extent))])
self.source.setSubsetString(None)
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
self.source.setSubsetString(subset)
@@ -174,7 +195,8 @@ def testSubsetString(self):
all_valid = (all(f.isValid() for f in self.source.getFeatures(request)))
self.source.setSubsetString(None)
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)

def getSubsetString(self):
@@ -330,8 +352,11 @@ def testExtent(self):
self.assertTrue(provider_extent.isNull())

def testUnique(self):
self.assertEqual(set(self.source.uniqueValues(self.source.fields().lookupField('cnt'))), 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'))))
self.assertEqual(set(self.source.uniqueValues(self.source.fields().lookupField('cnt'))),
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():
subset = self.getSubsetString2()
@@ -352,7 +377,8 @@ def testUniqueStringsMatching(self):
self.assertEqual(len(result), 2)
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():
subset = self.getSubsetString2()
@@ -365,7 +391,7 @@ def testFeatureCount(self):
self.assertEqual(self.source.featureCount(), 5)

if self.source.supportsSubsetString():
#Add a subset string and test feature count
# Add a subset string and test feature count
subset = self.getSubsetString()
self.source.setSubsetString(subset)
count = self.source.featureCount()
@@ -425,7 +451,8 @@ def testAddFeature(self):

else:
# 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):
if not getattr(self, 'getEditableLayer', None):
@@ -465,7 +492,8 @@ def testAddFeatureMissingAttributes(self):
f2.setAttributes([7, 330])

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())
f2.setId(added[1].id())

@@ -519,7 +547,8 @@ def testAddFeatureWrongGeomType(self):
f2.setAttributes([8])

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
added = [f for f in l.dataProvider().getFeatures() if f['pk'] == 7]
@@ -561,7 +590,7 @@ def testDeleteFeatures(self):
l = self.getEditableLayer()
self.assertTrue(l.isValid())

#find 2 features to delete
# find 2 features to delete
features = [f for f in l.dataProvider().getFeatures()]
to_delete = [f.id() for f in features if f.attributes()[0] in [1, 3]]

@@ -610,7 +639,8 @@ def testTruncate(self):
if l.dataProvider().capabilities() & QgsVectorDataProvider.FastTruncate or l.dataProvider().capabilities() & QgsVectorDataProvider.DeleteFeatures:
# expect success
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
features = [f['pk'] for f in l.dataProvider().getFeatures()]
@@ -627,7 +657,7 @@ def testChangeAttributes(self):
l = self.getEditableLayer()
self.assertTrue(l.isValid())

#find 2 features to change
# find 2 features to change
features = [f for f in l.dataProvider().getFeatures()]
# need to keep order here
to_change = [f for f in features if f.attributes()[0] == 1]
@@ -640,7 +670,8 @@ def testChangeAttributes(self):
if l.dataProvider().capabilities() & QgsVectorDataProvider.ChangeAttributeValues:
# expect success
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
self.testGetFeatures(l.dataProvider(), changed_attributes=new_attr_map)
@@ -733,3 +764,56 @@ def testChangeFeatures(self):
# expect fail
self.assertFalse(l.dataProvider().changeFeatures(attribute_changes, geometry_changes),
'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.

0 comments on commit 26174ea

Please sign in to comment.
You can’t perform that action at this time.