Merge "Fix bug in get_capabilities behavior in DB drivers"
This commit is contained in:
commit
6bd9038d90
@ -75,6 +75,24 @@ class DB2Storage(base.StorageEngine):
|
|||||||
return Connection(conf)
|
return Connection(conf)
|
||||||
|
|
||||||
|
|
||||||
|
AVAILABLE_CAPABILITIES = {
|
||||||
|
'meters': {'query': {'simple': True,
|
||||||
|
'metadata': True}},
|
||||||
|
'resources': {'query': {'simple': True,
|
||||||
|
'metadata': True}},
|
||||||
|
'samples': {'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': True}},
|
||||||
|
'statistics': {'groupby': True,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True},
|
||||||
|
'aggregation': {'standard': True}},
|
||||||
|
'alarms': {'query': {'simple': True,
|
||||||
|
'complex': True},
|
||||||
|
'history': {'query': {'simple': True}}},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Connection(pymongo_base.Connection):
|
class Connection(pymongo_base.Connection):
|
||||||
"""DB2 connection.
|
"""DB2 connection.
|
||||||
"""
|
"""
|
||||||
@ -132,6 +150,9 @@ class Connection(pymongo_base.Connection):
|
|||||||
self.db.authenticate(connection_options['username'],
|
self.db.authenticate(connection_options['username'],
|
||||||
connection_options['password'])
|
connection_options['password'])
|
||||||
|
|
||||||
|
self.CAPABILITIES = utils.update_nested(self.DEFAULT_CAPABILITIES,
|
||||||
|
AVAILABLE_CAPABILITIES)
|
||||||
|
|
||||||
self.upgrade()
|
self.upgrade()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -423,20 +444,4 @@ class Connection(pymongo_base.Connection):
|
|||||||
def get_capabilities(self):
|
def get_capabilities(self):
|
||||||
"""Return an dictionary representing the capabilities of this driver.
|
"""Return an dictionary representing the capabilities of this driver.
|
||||||
"""
|
"""
|
||||||
available = {
|
return self.CAPABILITIES
|
||||||
'meters': {'query': {'simple': True,
|
|
||||||
'metadata': True}},
|
|
||||||
'resources': {'query': {'simple': True,
|
|
||||||
'metadata': True}},
|
|
||||||
'samples': {'query': {'simple': True,
|
|
||||||
'metadata': True,
|
|
||||||
'complex': True}},
|
|
||||||
'statistics': {'groupby': True,
|
|
||||||
'query': {'simple': True,
|
|
||||||
'metadata': True},
|
|
||||||
'aggregation': {'standard': True}},
|
|
||||||
'alarms': {'query': {'simple': True,
|
|
||||||
'complex': True},
|
|
||||||
'history': {'query': {'simple': True}}},
|
|
||||||
}
|
|
||||||
return utils.update_nested(self.DEFAULT_CAPABILITIES, available)
|
|
||||||
|
@ -94,6 +94,19 @@ class HBaseStorage(base.StorageEngine):
|
|||||||
return Connection(conf)
|
return Connection(conf)
|
||||||
|
|
||||||
|
|
||||||
|
AVAILABLE_CAPABILITIES = {
|
||||||
|
'meters': {'query': {'simple': True,
|
||||||
|
'metadata': True}},
|
||||||
|
'resources': {'query': {'simple': True,
|
||||||
|
'metadata': True}},
|
||||||
|
'samples': {'query': {'simple': True,
|
||||||
|
'metadata': True}},
|
||||||
|
'statistics': {'query': {'simple': True,
|
||||||
|
'metadata': True},
|
||||||
|
'aggregation': {'standard': True}},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Connection(base.Connection):
|
class Connection(base.Connection):
|
||||||
"""HBase connection.
|
"""HBase connection.
|
||||||
"""
|
"""
|
||||||
@ -128,6 +141,9 @@ class Connection(base.Connection):
|
|||||||
self.conn = self._get_connection(opts)
|
self.conn = self._get_connection(opts)
|
||||||
self.conn.open()
|
self.conn.open()
|
||||||
|
|
||||||
|
self.CAPABILITIES = utils.update_nested(self.DEFAULT_CAPABILITIES,
|
||||||
|
AVAILABLE_CAPABILITIES)
|
||||||
|
|
||||||
def upgrade(self):
|
def upgrade(self):
|
||||||
self.conn.create_table(self.PROJECT_TABLE, {'f': dict()})
|
self.conn.create_table(self.PROJECT_TABLE, {'f': dict()})
|
||||||
self.conn.create_table(self.USER_TABLE, {'f': dict()})
|
self.conn.create_table(self.USER_TABLE, {'f': dict()})
|
||||||
@ -565,18 +581,7 @@ class Connection(base.Connection):
|
|||||||
def get_capabilities(self):
|
def get_capabilities(self):
|
||||||
"""Return an dictionary representing the capabilities of this driver.
|
"""Return an dictionary representing the capabilities of this driver.
|
||||||
"""
|
"""
|
||||||
available = {
|
return self.CAPABILITIES
|
||||||
'meters': {'query': {'simple': True,
|
|
||||||
'metadata': True}},
|
|
||||||
'resources': {'query': {'simple': True,
|
|
||||||
'metadata': True}},
|
|
||||||
'samples': {'query': {'simple': True,
|
|
||||||
'metadata': True}},
|
|
||||||
'statistics': {'query': {'simple': True,
|
|
||||||
'metadata': True},
|
|
||||||
'aggregation': {'standard': True}},
|
|
||||||
}
|
|
||||||
return utils.update_nested(self.DEFAULT_CAPABILITIES, available)
|
|
||||||
|
|
||||||
|
|
||||||
###############
|
###############
|
||||||
|
@ -82,6 +82,34 @@ class MongoDBStorage(base.StorageEngine):
|
|||||||
return Connection(conf)
|
return Connection(conf)
|
||||||
|
|
||||||
|
|
||||||
|
AVAILABLE_CAPABILITIES = {
|
||||||
|
'meters': {'query': {'simple': True,
|
||||||
|
'metadata': True}},
|
||||||
|
'resources': {'query': {'simple': True,
|
||||||
|
'metadata': True}},
|
||||||
|
'samples': {'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': True}},
|
||||||
|
'statistics': {'groupby': True,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True},
|
||||||
|
'aggregation': {'standard': True,
|
||||||
|
'selectable': {
|
||||||
|
'max': True,
|
||||||
|
'min': True,
|
||||||
|
'sum': True,
|
||||||
|
'avg': True,
|
||||||
|
'count': True,
|
||||||
|
'stddev': True,
|
||||||
|
'cardinality': True}}
|
||||||
|
},
|
||||||
|
'alarms': {'query': {'simple': True,
|
||||||
|
'complex': True},
|
||||||
|
'history': {'query': {'simple': True,
|
||||||
|
'complex': True}}},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Connection(pymongo_base.Connection):
|
class Connection(pymongo_base.Connection):
|
||||||
"""MongoDB connection.
|
"""MongoDB connection.
|
||||||
"""
|
"""
|
||||||
@ -409,6 +437,9 @@ class Connection(pymongo_base.Connection):
|
|||||||
self.db.authenticate(connection_options['username'],
|
self.db.authenticate(connection_options['username'],
|
||||||
connection_options['password'])
|
connection_options['password'])
|
||||||
|
|
||||||
|
self.CAPABILITIES = utils.update_nested(self.DEFAULT_CAPABILITIES,
|
||||||
|
AVAILABLE_CAPABILITIES)
|
||||||
|
|
||||||
# NOTE(jd) Upgrading is just about creating index, so let's do this
|
# NOTE(jd) Upgrading is just about creating index, so let's do this
|
||||||
# on connection to be sure at least the TTL is correcly updated if
|
# on connection to be sure at least the TTL is correcly updated if
|
||||||
# needed.
|
# needed.
|
||||||
@ -956,30 +987,4 @@ class Connection(pymongo_base.Connection):
|
|||||||
def get_capabilities(self):
|
def get_capabilities(self):
|
||||||
"""Return an dictionary representing the capabilities of this driver.
|
"""Return an dictionary representing the capabilities of this driver.
|
||||||
"""
|
"""
|
||||||
available = {
|
return self.CAPABILITIES
|
||||||
'meters': {'query': {'simple': True,
|
|
||||||
'metadata': True}},
|
|
||||||
'resources': {'query': {'simple': True,
|
|
||||||
'metadata': True}},
|
|
||||||
'samples': {'query': {'simple': True,
|
|
||||||
'metadata': True,
|
|
||||||
'complex': True}},
|
|
||||||
'statistics': {'groupby': True,
|
|
||||||
'query': {'simple': True,
|
|
||||||
'metadata': True},
|
|
||||||
'aggregation': {'standard': True,
|
|
||||||
'selectable': {
|
|
||||||
'max': True,
|
|
||||||
'min': True,
|
|
||||||
'sum': True,
|
|
||||||
'avg': True,
|
|
||||||
'count': True,
|
|
||||||
'stddev': True,
|
|
||||||
'cardinality': True}}
|
|
||||||
},
|
|
||||||
'alarms': {'query': {'simple': True,
|
|
||||||
'complex': True},
|
|
||||||
'history': {'query': {'simple': True,
|
|
||||||
'complex': True}}},
|
|
||||||
}
|
|
||||||
return utils.update_nested(self.DEFAULT_CAPABILITIES, available)
|
|
||||||
|
@ -133,6 +133,36 @@ PARAMETERIZED_AGGREGATES = dict(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AVAILABLE_CAPABILITIES = {
|
||||||
|
'meters': {'query': {'simple': True,
|
||||||
|
'metadata': True}},
|
||||||
|
'resources': {'query': {'simple': True,
|
||||||
|
'metadata': True}},
|
||||||
|
'samples': {'pagination': True,
|
||||||
|
'groupby': True,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': True}},
|
||||||
|
'statistics': {'groupby': True,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True},
|
||||||
|
'aggregation': {'standard': True,
|
||||||
|
'selectable': {
|
||||||
|
'max': True,
|
||||||
|
'min': True,
|
||||||
|
'sum': True,
|
||||||
|
'avg': True,
|
||||||
|
'count': True,
|
||||||
|
'stddev': True,
|
||||||
|
'cardinality': True}}
|
||||||
|
},
|
||||||
|
'alarms': {'query': {'simple': True,
|
||||||
|
'complex': True},
|
||||||
|
'history': {'query': {'simple': True,
|
||||||
|
'complex': True}}},
|
||||||
|
'events': {'query': {'simple': True}},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def apply_metaquery_filter(session, query, metaquery):
|
def apply_metaquery_filter(session, query, metaquery):
|
||||||
"""Apply provided metaquery filter to existing query.
|
"""Apply provided metaquery filter to existing query.
|
||||||
@ -223,6 +253,8 @@ class Connection(base.Connection):
|
|||||||
self._maker = sqlalchemy_session.get_maker(self._engine)
|
self._maker = sqlalchemy_session.get_maker(self._engine)
|
||||||
sqlalchemy_session._ENGINE = None
|
sqlalchemy_session._ENGINE = None
|
||||||
sqlalchemy_session._MAKER = None
|
sqlalchemy_session._MAKER = None
|
||||||
|
self._CAPABILITIES = utils.update_nested(self.DEFAULT_CAPABILITIES,
|
||||||
|
AVAILABLE_CAPABILITIES)
|
||||||
|
|
||||||
def _get_db_session(self):
|
def _get_db_session(self):
|
||||||
return self._maker()
|
return self._maker()
|
||||||
@ -1262,6 +1294,11 @@ class Connection(base.Connection):
|
|||||||
dtype=type.data_type,
|
dtype=type.data_type,
|
||||||
value=trait.get_value())
|
value=trait.get_value())
|
||||||
|
|
||||||
|
def get_capabilities(self):
|
||||||
|
"""Return an dictionary representing the capabilities of this driver.
|
||||||
|
"""
|
||||||
|
return self._CAPABILITIES
|
||||||
|
|
||||||
|
|
||||||
class QueryTransformer(object):
|
class QueryTransformer(object):
|
||||||
operators = {"=": operator.eq,
|
operators = {"=": operator.eq,
|
||||||
@ -1349,37 +1386,3 @@ class QueryTransformer(object):
|
|||||||
|
|
||||||
def get_query(self):
|
def get_query(self):
|
||||||
return self.query
|
return self.query
|
||||||
|
|
||||||
def get_capabilities(self):
|
|
||||||
"""Return an dictionary representing the capabilities of this driver.
|
|
||||||
"""
|
|
||||||
available = {
|
|
||||||
'meters': {'query': {'simple': True,
|
|
||||||
'metadata': True}},
|
|
||||||
'resources': {'query': {'simple': True,
|
|
||||||
'metadata': True}},
|
|
||||||
'samples': {'pagination': True,
|
|
||||||
'groupby': True,
|
|
||||||
'query': {'simple': True,
|
|
||||||
'metadata': True,
|
|
||||||
'complex': True}},
|
|
||||||
'statistics': {'groupby': True,
|
|
||||||
'query': {'simple': True,
|
|
||||||
'metadata': True},
|
|
||||||
'aggregation': {'standard': True,
|
|
||||||
'selectable': {
|
|
||||||
'max': True,
|
|
||||||
'min': True,
|
|
||||||
'sum': True,
|
|
||||||
'avg': True,
|
|
||||||
'count': True,
|
|
||||||
'stddev': True,
|
|
||||||
'cardinality': True}}
|
|
||||||
},
|
|
||||||
'alarms': {'query': {'simple': True,
|
|
||||||
'complex': True},
|
|
||||||
'history': {'query': {'simple': True,
|
|
||||||
'complex': True}}},
|
|
||||||
'events': {'query': {'simple': True}},
|
|
||||||
}
|
|
||||||
return utils.update_nested(self.DEFAULT_CAPABILITIES, available)
|
|
||||||
|
37
ceilometer/tests/api/v2/test_capabilities.py
Normal file
37
ceilometer/tests/api/v2/test_capabilities.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright Ericsson AB 2014. All rights reserved
|
||||||
|
#
|
||||||
|
# Authors: Ildiko Vancsa <ildiko.vancsa@ericsson.com>
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import testscenarios
|
||||||
|
|
||||||
|
from ceilometer.tests.api import v2 as tests_api
|
||||||
|
from ceilometer.tests import db as tests_db
|
||||||
|
|
||||||
|
load_tests = testscenarios.load_tests_apply_scenarios
|
||||||
|
|
||||||
|
|
||||||
|
class TestCapabilitiesController(tests_api.FunctionalTest,
|
||||||
|
tests_db.MixinTestsWithBackendScenarios):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestCapabilitiesController, self).setUp()
|
||||||
|
self.url = '/capabilities'
|
||||||
|
|
||||||
|
def test_capabilities(self):
|
||||||
|
data = self.get_json(self.url)
|
||||||
|
self.assertIsNotNone(data)
|
||||||
|
self.assertNotEqual({}, data)
|
76
ceilometer/tests/storage/test_impl_db2.py
Normal file
76
ceilometer/tests/storage/test_impl_db2.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright Ericsson AB 2014. All rights reserved
|
||||||
|
#
|
||||||
|
# Authors: Ildiko Vancsa <ildiko.vancsa@ericsson.com>
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
"""Tests for ceilometer/storage/impl_db2.py
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
In order to run the tests against another MongoDB server set the
|
||||||
|
environment variable CEILOMETER_TEST_DB2_URL to point to a DB2
|
||||||
|
server before running the tests.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ceilometer.tests import db as tests_db
|
||||||
|
|
||||||
|
|
||||||
|
class DB2EngineTestBase(tests_db.TestBase):
|
||||||
|
database_connection = tests_db.DB2FakeConnectionUrl()
|
||||||
|
|
||||||
|
|
||||||
|
class CapabilitiesTest(DB2EngineTestBase):
|
||||||
|
# Check the returned capabilities list, which is specific to each DB
|
||||||
|
# driver
|
||||||
|
|
||||||
|
def test_capabilities(self):
|
||||||
|
expected_capabilities = {
|
||||||
|
'meters': {'pagination': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False}},
|
||||||
|
'resources': {'pagination': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False}},
|
||||||
|
'samples': {'pagination': False,
|
||||||
|
'groupby': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': True}},
|
||||||
|
'statistics': {'pagination': False,
|
||||||
|
'groupby': True,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False},
|
||||||
|
'aggregation': {'standard': True,
|
||||||
|
'selectable': {
|
||||||
|
'max': False,
|
||||||
|
'min': False,
|
||||||
|
'sum': False,
|
||||||
|
'avg': False,
|
||||||
|
'count': False,
|
||||||
|
'stddev': False,
|
||||||
|
'cardinality': False}}
|
||||||
|
},
|
||||||
|
'alarms': {'query': {'simple': True,
|
||||||
|
'complex': True},
|
||||||
|
'history': {'query': {'simple': True,
|
||||||
|
'complex': False}}},
|
||||||
|
'events': {'query': {'simple': False}}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual_capabilities = self.conn.get_capabilities()
|
||||||
|
self.assertEqual(expected_capabilities, actual_capabilities)
|
@ -56,3 +56,48 @@ class ConnectionTest(HBaseEngineTestBase):
|
|||||||
side_effect=get_connection):
|
side_effect=get_connection):
|
||||||
conn = hbase.Connection(self.CONF)
|
conn = hbase.Connection(self.CONF)
|
||||||
self.assertIsInstance(conn.conn, TestConn)
|
self.assertIsInstance(conn.conn, TestConn)
|
||||||
|
|
||||||
|
|
||||||
|
class CapabilitiesTest(HBaseEngineTestBase):
|
||||||
|
# Check the returned capabilities list, which is specific to each DB
|
||||||
|
# driver
|
||||||
|
|
||||||
|
def test_capabilities(self):
|
||||||
|
expected_capabilities = {
|
||||||
|
'meters': {'pagination': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False}},
|
||||||
|
'resources': {'pagination': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False}},
|
||||||
|
'samples': {'pagination': False,
|
||||||
|
'groupby': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False}},
|
||||||
|
'statistics': {'pagination': False,
|
||||||
|
'groupby': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False},
|
||||||
|
'aggregation': {'standard': True,
|
||||||
|
'selectable': {
|
||||||
|
'max': False,
|
||||||
|
'min': False,
|
||||||
|
'sum': False,
|
||||||
|
'avg': False,
|
||||||
|
'count': False,
|
||||||
|
'stddev': False,
|
||||||
|
'cardinality': False}}
|
||||||
|
},
|
||||||
|
'alarms': {'query': {'simple': False,
|
||||||
|
'complex': False},
|
||||||
|
'history': {'query': {'simple': False,
|
||||||
|
'complex': False}}},
|
||||||
|
'events': {'query': {'simple': False}}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual_capabilities = self.conn.get_capabilities()
|
||||||
|
self.assertEqual(expected_capabilities, actual_capabilities)
|
||||||
|
@ -144,3 +144,48 @@ class AlarmTestPagination(test_storage_scenarios.AlarmTestBase,
|
|||||||
'counter-name-foo')
|
'counter-name-foo')
|
||||||
except base.MultipleResultsFound:
|
except base.MultipleResultsFound:
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
|
||||||
|
class CapabilitiesTest(MongoDBEngineTestBase):
|
||||||
|
# Check the returned capabilities list, which is specific to each DB
|
||||||
|
# driver
|
||||||
|
|
||||||
|
def test_capabilities(self):
|
||||||
|
expected_capabilities = {
|
||||||
|
'meters': {'pagination': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False}},
|
||||||
|
'resources': {'pagination': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False}},
|
||||||
|
'samples': {'pagination': False,
|
||||||
|
'groupby': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': True}},
|
||||||
|
'statistics': {'pagination': False,
|
||||||
|
'groupby': True,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False},
|
||||||
|
'aggregation': {'standard': True,
|
||||||
|
'selectable': {
|
||||||
|
'max': True,
|
||||||
|
'min': True,
|
||||||
|
'sum': True,
|
||||||
|
'avg': True,
|
||||||
|
'count': True,
|
||||||
|
'stddev': True,
|
||||||
|
'cardinality': True}}
|
||||||
|
},
|
||||||
|
'alarms': {'query': {'simple': True,
|
||||||
|
'complex': True},
|
||||||
|
'history': {'query': {'simple': True,
|
||||||
|
'complex': True}}},
|
||||||
|
'events': {'query': {'simple': False}}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual_capabilities = self.conn.get_capabilities()
|
||||||
|
self.assertEqual(expected_capabilities, actual_capabilities)
|
||||||
|
@ -222,3 +222,48 @@ class RelationshipTest(scenarios.DBTestBase):
|
|||||||
session.query(sql_models.User.id)
|
session.query(sql_models.User.id)
|
||||||
.group_by(sql_models.User.id)
|
.group_by(sql_models.User.id)
|
||||||
)).count(), 0)
|
)).count(), 0)
|
||||||
|
|
||||||
|
|
||||||
|
class CapabilitiesTest(EventTestBase):
|
||||||
|
# Check the returned capabilities list, which is specific to each DB
|
||||||
|
# driver
|
||||||
|
|
||||||
|
def test_capabilities(self):
|
||||||
|
expected_capabilities = {
|
||||||
|
'meters': {'pagination': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False}},
|
||||||
|
'resources': {'pagination': False,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False}},
|
||||||
|
'samples': {'pagination': True,
|
||||||
|
'groupby': True,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': True}},
|
||||||
|
'statistics': {'pagination': False,
|
||||||
|
'groupby': True,
|
||||||
|
'query': {'simple': True,
|
||||||
|
'metadata': True,
|
||||||
|
'complex': False},
|
||||||
|
'aggregation': {'standard': True,
|
||||||
|
'selectable': {
|
||||||
|
'max': True,
|
||||||
|
'min': True,
|
||||||
|
'sum': True,
|
||||||
|
'avg': True,
|
||||||
|
'count': True,
|
||||||
|
'stddev': True,
|
||||||
|
'cardinality': True}}
|
||||||
|
},
|
||||||
|
'alarms': {'query': {'simple': True,
|
||||||
|
'complex': True},
|
||||||
|
'history': {'query': {'simple': True,
|
||||||
|
'complex': True}}},
|
||||||
|
'events': {'query': {'simple': True}}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual_capabilities = self.conn.get_capabilities()
|
||||||
|
self.assertEqual(expected_capabilities, actual_capabilities)
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
"""Utilities and helper functions."""
|
"""Utilities and helper functions."""
|
||||||
|
|
||||||
import calendar
|
import calendar
|
||||||
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import decimal
|
import decimal
|
||||||
|
|
||||||
@ -134,14 +135,15 @@ def lowercase_values(mapping):
|
|||||||
mapping[key] = value.lower()
|
mapping[key] = value.lower()
|
||||||
|
|
||||||
|
|
||||||
def update_nested(d, u):
|
def update_nested(original_dict, updates):
|
||||||
"""Updates the leaf nodes in a nest dict, without replacing
|
"""Updates the leaf nodes in a nest dict, without replacing
|
||||||
entire sub-dicts.
|
entire sub-dicts.
|
||||||
"""
|
"""
|
||||||
for k, v in u.iteritems():
|
dict_to_update = copy.deepcopy(original_dict)
|
||||||
if isinstance(v, dict):
|
for key, value in updates.iteritems():
|
||||||
r = update_nested(d.get(k, {}), v)
|
if isinstance(value, dict):
|
||||||
d[k] = r
|
sub_dict = update_nested(dict_to_update.get(key, {}), value)
|
||||||
|
dict_to_update[key] = sub_dict
|
||||||
else:
|
else:
|
||||||
d[k] = u[k]
|
dict_to_update[key] = updates[key]
|
||||||
return d
|
return dict_to_update
|
||||||
|
Loading…
x
Reference in New Issue
Block a user