a20158766b
The goal of this changeset is to enable at least some of the tests to be run under Python3. Even if we can't get them all to run initially it's important that we start seeing the changes from bp keystone-py3kcompat. Also it's important that we are checking for regressions. If we do all this Python 3 work, but don't have automated tests in place we may inadvertantly undo that work. In this initial changeset I had to do some not nice things to get this to work. First I had to switch to using the nose test runner. testr seems to be much more aggressive about importing everything, even when you are not going to run the test module. This idea came from oslo. Once we have full Python 3 support we can go back to testr. Then I had to mock out some of the libraries that don't work on Python 3. This is unfortunate, but had to be done because keystone.test.core indirectly imports a significant amount of the codebase. bp python3 Change-Id: I6dd0d1b84380c4c386f70b72cdfcdf9b744c755f
729 lines
27 KiB
Python
729 lines
27 KiB
Python
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
#
|
|
# 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 collections
|
|
import copy
|
|
import functools
|
|
import uuid
|
|
|
|
from dogpile.cache import api
|
|
from dogpile.cache import region as dp_region
|
|
import six
|
|
|
|
from keystone.common.cache.backends import mongo
|
|
from keystone import exception
|
|
from keystone import tests
|
|
|
|
|
|
# Mock database structure sample where 'ks_cache' is database and
|
|
# 'cache' is collection. Dogpile CachedValue data is divided in two
|
|
# fields `value` (CachedValue.payload) and `meta` (CachedValue.metadata)
|
|
ks_cache = {
|
|
"cache": [
|
|
{
|
|
"value": {
|
|
"serviceType": "identity",
|
|
"allVersionsUrl": "https://dummyUrl",
|
|
"dateLastModified": "ISODDate(2014-02-08T18:39:13.237Z)",
|
|
"serviceName": "Identity",
|
|
"enabled": "True"
|
|
},
|
|
"meta": {
|
|
"v": 1,
|
|
"ct": 1392371422.015121
|
|
},
|
|
"doc_date": "ISODate('2014-02-14T09:50:22.015Z')",
|
|
"_id": "8251dc95f63842719c077072f1047ddf"
|
|
},
|
|
{
|
|
"value": "dummyValueX",
|
|
"meta": {
|
|
"v": 1,
|
|
"ct": 1392371422.014058
|
|
},
|
|
"doc_date": "ISODate('2014-02-14T09:50:22.014Z')",
|
|
"_id": "66730b9534d146f0804d23729ad35436"
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
COLLECTIONS = {}
|
|
SON_MANIPULATOR = None
|
|
|
|
|
|
class MockCursor(object):
|
|
|
|
def __init__(self, collection, dataset_factory):
|
|
super(MockCursor, self).__init__()
|
|
self.collection = collection
|
|
self._factory = dataset_factory
|
|
self._dataset = self._factory()
|
|
self._limit = None
|
|
self._skip = None
|
|
|
|
def __iter__(self):
|
|
return self
|
|
|
|
def __next__(self):
|
|
if self._skip:
|
|
for _ in range(self._skip):
|
|
next(self._dataset)
|
|
self._skip = None
|
|
if self._limit is not None and self._limit <= 0:
|
|
raise StopIteration()
|
|
if self._limit is not None:
|
|
self._limit -= 1
|
|
return next(self._dataset)
|
|
|
|
next = __next__
|
|
|
|
def __getitem__(self, index):
|
|
arr = [x for x in self._dataset]
|
|
self._dataset = iter(arr)
|
|
return arr[index]
|
|
|
|
|
|
class MockCollection(object):
|
|
|
|
def __init__(self, db, name):
|
|
super(MockCollection, self).__init__()
|
|
self.name = name
|
|
self._collection_database = db
|
|
self._documents = {}
|
|
self.write_concern = {}
|
|
|
|
def __getattr__(self, name):
|
|
if name == 'database':
|
|
return self._collection_database
|
|
|
|
def ensure_index(self, key_or_list, *args, **kwargs):
|
|
pass
|
|
|
|
def index_information(self):
|
|
return {}
|
|
|
|
def find_one(self, spec_or_id=None, *args, **kwargs):
|
|
if spec_or_id is None:
|
|
spec_or_id = {}
|
|
if not isinstance(spec_or_id, collections.Mapping):
|
|
spec_or_id = {'_id': spec_or_id}
|
|
|
|
try:
|
|
return next(self.find(spec_or_id, *args, **kwargs))
|
|
except StopIteration:
|
|
return None
|
|
|
|
def find(self, spec=None, *args, **kwargs):
|
|
return MockCursor(self, functools.partial(self._get_dataset, spec))
|
|
|
|
def _get_dataset(self, spec):
|
|
dataset = (self._copy_doc(document, dict) for document in
|
|
self._iter_documents(spec))
|
|
return dataset
|
|
|
|
def _iter_documents(self, spec=None):
|
|
return (SON_MANIPULATOR.transform_outgoing(document, self) for
|
|
document in six.itervalues(self._documents)
|
|
if self._apply_filter(document, spec))
|
|
|
|
def _apply_filter(self, document, query):
|
|
for key, search in six.iteritems(query):
|
|
doc_val = document.get(key)
|
|
if isinstance(search, dict):
|
|
op_dict = {'$in': lambda dv, sv: dv in sv}
|
|
is_match = all(
|
|
op_str in op_dict and op_dict[op_str](doc_val, search_val)
|
|
for op_str, search_val in six.iteritems(search)
|
|
)
|
|
else:
|
|
is_match = doc_val == search
|
|
|
|
return is_match
|
|
|
|
def _copy_doc(self, obj, container):
|
|
if isinstance(obj, list):
|
|
new = []
|
|
for item in obj:
|
|
new.append(self._copy_doc(item, container))
|
|
return new
|
|
if isinstance(obj, dict):
|
|
new = container()
|
|
for key, value in obj.items():
|
|
new[key] = self._copy_doc(value, container)
|
|
return new
|
|
else:
|
|
return copy.copy(obj)
|
|
|
|
def insert(self, data, manipulate=True, **kwargs):
|
|
if isinstance(data, list):
|
|
return [self._insert(element) for element in data]
|
|
return self._insert(data)
|
|
|
|
def save(self, data, manipulate=True, **kwargs):
|
|
return self._insert(data)
|
|
|
|
def _insert(self, data):
|
|
if '_id' not in data:
|
|
data['_id'] = uuid.uuid4().hex
|
|
object_id = data['_id']
|
|
self._documents[object_id] = self._internalize_dict(data)
|
|
return object_id
|
|
|
|
def find_and_modify(self, spec, document, upsert=False, **kwargs):
|
|
self.update(spec, document, upsert, **kwargs)
|
|
|
|
def update(self, spec, document, upsert=False, **kwargs):
|
|
|
|
existing_docs = [doc for doc in six.itervalues(self._documents)
|
|
if self._apply_filter(doc, spec)]
|
|
if existing_docs:
|
|
existing_doc = existing_docs[0] # should find only 1 match
|
|
_id = existing_doc['_id']
|
|
existing_doc.clear()
|
|
existing_doc['_id'] = _id
|
|
existing_doc.update(self._internalize_dict(document))
|
|
elif upsert:
|
|
existing_doc = self._documents[self._insert(document)]
|
|
|
|
def _internalize_dict(self, d):
|
|
return dict((k, copy.deepcopy(v)) for k, v in six.iteritems(d))
|
|
|
|
def remove(self, spec_or_id=None, search_filter=None):
|
|
"""Remove objects matching spec_or_id from the collection."""
|
|
if spec_or_id is None:
|
|
spec_or_id = search_filter if search_filter else {}
|
|
if not isinstance(spec_or_id, dict):
|
|
spec_or_id = {'_id': spec_or_id}
|
|
to_delete = list(self.find(spec=spec_or_id))
|
|
for doc in to_delete:
|
|
doc_id = doc['_id']
|
|
del self._documents[doc_id]
|
|
|
|
return {
|
|
"connectionId": uuid.uuid4().hex,
|
|
"n": len(to_delete),
|
|
"ok": 1.0,
|
|
"err": None,
|
|
}
|
|
|
|
|
|
class MockMongoDB(object):
|
|
def __init__(self, dbname):
|
|
self._dbname = dbname
|
|
self.mainpulator = None
|
|
|
|
def authenticate(self, username, password):
|
|
pass
|
|
|
|
def add_son_manipulator(self, manipulator):
|
|
global SON_MANIPULATOR
|
|
SON_MANIPULATOR = manipulator
|
|
|
|
def __getattr__(self, name):
|
|
if name == 'authenticate':
|
|
return self.authenticate
|
|
elif name == 'name':
|
|
return self._dbname
|
|
elif name == 'add_son_manipulator':
|
|
return self.add_son_manipulator
|
|
else:
|
|
return get_collection(self._dbname, name)
|
|
|
|
def __getitem__(self, name):
|
|
return get_collection(self._dbname, name)
|
|
|
|
|
|
class MockMongoClient(object):
|
|
def __init__(self, *args, **kwargs):
|
|
pass
|
|
|
|
def __getattr__(self, dbname):
|
|
return MockMongoDB(dbname)
|
|
|
|
|
|
def get_collection(db_name, collection_name):
|
|
mongo_collection = MockCollection(MockMongoDB(db_name), collection_name)
|
|
return mongo_collection
|
|
|
|
|
|
def pymongo_override():
|
|
global pymongo
|
|
import pymongo
|
|
if pymongo.MongoClient is not MockMongoClient:
|
|
pymongo.MongoClient = MockMongoClient
|
|
if pymongo.MongoReplicaSetClient is not MockMongoClient:
|
|
pymongo.MongoClient = MockMongoClient
|
|
|
|
|
|
class MyTransformer(mongo.BaseTransform):
|
|
"""Added here just to check manipulator logic is used correctly."""
|
|
|
|
def transform_incoming(self, son, collection):
|
|
return super(MyTransformer, self).transform_incoming(son, collection)
|
|
|
|
def transform_outgoing(self, son, collection):
|
|
return super(MyTransformer, self).transform_outgoing(son, collection)
|
|
|
|
|
|
class MongoCache(tests.BaseTestCase):
|
|
def setUp(self):
|
|
super(MongoCache, self).setUp()
|
|
global COLLECTIONS
|
|
COLLECTIONS = {}
|
|
mongo.MongoApi._DB = {}
|
|
mongo.MongoApi._MONGO_COLLS = {}
|
|
pymongo_override()
|
|
# using typical configuration
|
|
self.arguments = {
|
|
'db_hosts': 'localhost:27017',
|
|
'db_name': 'ks_cache',
|
|
'cache_collection': 'cache',
|
|
'username': 'test_user',
|
|
'password': 'test_password'
|
|
}
|
|
|
|
def test_missing_db_hosts(self):
|
|
self.arguments.pop('db_hosts')
|
|
region = dp_region.make_region()
|
|
self.assertRaises(exception.ValidationError, region.configure,
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
|
|
def test_missing_db_name(self):
|
|
self.arguments.pop('db_name')
|
|
region = dp_region.make_region()
|
|
self.assertRaises(exception.ValidationError, region.configure,
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
|
|
def test_missing_cache_collection_name(self):
|
|
self.arguments.pop('cache_collection')
|
|
region = dp_region.make_region()
|
|
self.assertRaises(exception.ValidationError, region.configure,
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
|
|
def test_incorrect_write_concern(self):
|
|
self.arguments['w'] = 'one value'
|
|
region = dp_region.make_region()
|
|
self.assertRaises(exception.ValidationError, region.configure,
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
|
|
def test_correct_write_concern(self):
|
|
self.arguments['w'] = 1
|
|
region = dp_region.make_region().configure('keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, "dummyValue10")
|
|
# There is no proxy so can access MongoCacheBackend directly
|
|
self.assertEqual(region.backend.api.w, 1)
|
|
|
|
def test_incorrect_read_preference(self):
|
|
self.arguments['read_preference'] = 'inValidValue'
|
|
region = dp_region.make_region().configure('keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
# As per delayed loading of pymongo, read_preference value should
|
|
# still be string and NOT enum
|
|
self.assertEqual(region.backend.api.read_preference,
|
|
'inValidValue')
|
|
|
|
random_key = uuid.uuid4().hex
|
|
self.assertRaises(ValueError, region.set,
|
|
random_key, "dummyValue10")
|
|
|
|
def test_correct_read_preference(self):
|
|
self.arguments['read_preference'] = 'secondaryPreferred'
|
|
region = dp_region.make_region().configure('keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
# As per delayed loading of pymongo, read_preference value should
|
|
# still be string and NOT enum
|
|
self.assertEqual(region.backend.api.read_preference,
|
|
'secondaryPreferred')
|
|
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, "dummyValue10")
|
|
|
|
# Now as pymongo is loaded so expected read_preference value is enum.
|
|
# There is no proxy so can access MongoCacheBackend directly
|
|
self.assertEqual(region.backend.api.read_preference, 3)
|
|
|
|
def test_missing_replica_set_name(self):
|
|
self.arguments['use_replica'] = True
|
|
region = dp_region.make_region()
|
|
self.assertRaises(exception.ValidationError, region.configure,
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
|
|
def test_provided_replica_set_name(self):
|
|
self.arguments['use_replica'] = True
|
|
self.arguments['replicaset_name'] = 'my_replica'
|
|
dp_region.make_region().configure('keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
self.assertTrue(True) # reached here means no initialization error
|
|
|
|
def test_incorrect_mongo_ttl_seconds(self):
|
|
self.arguments['mongo_ttl_seconds'] = 'sixty'
|
|
region = dp_region.make_region()
|
|
self.assertRaises(exception.ValidationError, region.configure,
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
|
|
def test_cache_configuration_values_assertion(self):
|
|
self.arguments['use_replica'] = True
|
|
self.arguments['replicaset_name'] = 'my_replica'
|
|
self.arguments['mongo_ttl_seconds'] = 60
|
|
self.arguments['ssl'] = False
|
|
region = dp_region.make_region().configure('keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
# There is no proxy so can access MongoCacheBackend directly
|
|
self.assertEqual(region.backend.api.hosts, 'localhost:27017')
|
|
self.assertEqual(region.backend.api.db_name, 'ks_cache')
|
|
self.assertEqual(region.backend.api.cache_collection, 'cache')
|
|
self.assertEqual(region.backend.api.username, 'test_user')
|
|
self.assertEqual(region.backend.api.password, 'test_password')
|
|
self.assertEqual(region.backend.api.use_replica, True)
|
|
self.assertEqual(region.backend.api.replicaset_name, 'my_replica')
|
|
self.assertEqual(region.backend.api.conn_kwargs['ssl'], False)
|
|
self.assertEqual(region.backend.api.ttl_seconds, 60)
|
|
|
|
def test_multiple_region_cache_configuration(self):
|
|
arguments1 = copy.copy(self.arguments)
|
|
arguments1['cache_collection'] = 'cache_region1'
|
|
|
|
region1 = dp_region.make_region().configure('keystone.cache.mongo',
|
|
arguments=arguments1)
|
|
# There is no proxy so can access MongoCacheBackend directly
|
|
self.assertEqual(region1.backend.api.hosts, 'localhost:27017')
|
|
self.assertEqual(region1.backend.api.db_name, 'ks_cache')
|
|
self.assertEqual(region1.backend.api.cache_collection, 'cache_region1')
|
|
self.assertEqual(region1.backend.api.username, 'test_user')
|
|
self.assertEqual(region1.backend.api.password, 'test_password')
|
|
# Should be None because of delayed initialization
|
|
self.assertIsNone(region1.backend.api._data_manipulator)
|
|
|
|
random_key1 = uuid.uuid4().hex
|
|
region1.set(random_key1, "dummyValue10")
|
|
self.assertEqual("dummyValue10", region1.get(random_key1))
|
|
# Now should have initialized
|
|
self.assertIsInstance(region1.backend.api._data_manipulator,
|
|
mongo.BaseTransform)
|
|
|
|
class_name = '%s.%s' % (MyTransformer.__module__, "MyTransformer")
|
|
|
|
arguments2 = copy.copy(self.arguments)
|
|
arguments2['cache_collection'] = 'cache_region2'
|
|
arguments2['son_manipulator'] = class_name
|
|
|
|
region2 = dp_region.make_region().configure('keystone.cache.mongo',
|
|
arguments=arguments2)
|
|
# There is no proxy so can access MongoCacheBackend directly
|
|
self.assertEqual(region2.backend.api.hosts, 'localhost:27017')
|
|
self.assertEqual(region2.backend.api.db_name, 'ks_cache')
|
|
self.assertEqual(region2.backend.api.cache_collection, 'cache_region2')
|
|
|
|
# Should be None because of delayed initialization
|
|
self.assertIsNone(region2.backend.api._data_manipulator)
|
|
|
|
random_key = uuid.uuid4().hex
|
|
region2.set(random_key, "dummyValue20")
|
|
self.assertEqual("dummyValue20", region2.get(random_key))
|
|
# Now should have initialized
|
|
self.assertIsInstance(region2.backend.api._data_manipulator,
|
|
MyTransformer)
|
|
|
|
region1.set(random_key1, "dummyValue22")
|
|
self.assertEqual("dummyValue22", region1.get(random_key1))
|
|
|
|
def test_typical_configuration(self):
|
|
|
|
dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
self.assertTrue(True) # reached here means no initialization error
|
|
|
|
def test_backend_get_missing_data(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
|
|
random_key = uuid.uuid4().hex
|
|
# should return NO_VALUE as key does not exist in cache
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key))
|
|
|
|
def test_backend_set_data(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, "dummyValue")
|
|
self.assertEqual("dummyValue", region.get(random_key))
|
|
|
|
def test_backend_set_data_with_string_as_valid_ttl(self):
|
|
|
|
self.arguments['mongo_ttl_seconds'] = '3600'
|
|
region = dp_region.make_region().configure('keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
self.assertEqual(region.backend.api.ttl_seconds, 3600)
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, "dummyValue")
|
|
self.assertEqual("dummyValue", region.get(random_key))
|
|
|
|
def test_backend_set_data_with_int_as_valid_ttl(self):
|
|
|
|
self.arguments['mongo_ttl_seconds'] = 1800
|
|
region = dp_region.make_region().configure('keystone.cache.mongo',
|
|
arguments=self.arguments)
|
|
self.assertEqual(region.backend.api.ttl_seconds, 1800)
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, "dummyValue")
|
|
self.assertEqual("dummyValue", region.get(random_key))
|
|
|
|
def test_backend_set_none_as_data(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, None)
|
|
self.assertIsNone(region.get(random_key))
|
|
|
|
def test_backend_set_blank_as_data(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, "")
|
|
self.assertEqual("", region.get(random_key))
|
|
|
|
def test_backend_set_same_key_multiple_times(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, "dummyValue")
|
|
self.assertEqual("dummyValue", region.get(random_key))
|
|
|
|
dict_value = {'key1': 'value1'}
|
|
region.set(random_key, dict_value)
|
|
self.assertEqual(dict_value, region.get(random_key))
|
|
|
|
region.set(random_key, "dummyValue2")
|
|
self.assertEqual("dummyValue2", region.get(random_key))
|
|
|
|
def test_backend_multi_set_data(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
random_key = uuid.uuid4().hex
|
|
random_key1 = uuid.uuid4().hex
|
|
random_key2 = uuid.uuid4().hex
|
|
random_key3 = uuid.uuid4().hex
|
|
mapping = {random_key1: 'dummyValue1',
|
|
random_key2: 'dummyValue2',
|
|
random_key3: 'dummyValue3'}
|
|
region.set_multi(mapping)
|
|
# should return NO_VALUE as key does not exist in cache
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key))
|
|
self.assertFalse(region.get(random_key))
|
|
self.assertEqual("dummyValue1", region.get(random_key1))
|
|
self.assertEqual("dummyValue2", region.get(random_key2))
|
|
self.assertEqual("dummyValue3", region.get(random_key3))
|
|
|
|
def test_backend_multi_get_data(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
random_key = uuid.uuid4().hex
|
|
random_key1 = uuid.uuid4().hex
|
|
random_key2 = uuid.uuid4().hex
|
|
random_key3 = uuid.uuid4().hex
|
|
mapping = {random_key1: 'dummyValue1',
|
|
random_key2: '',
|
|
random_key3: 'dummyValue3'}
|
|
region.set_multi(mapping)
|
|
|
|
keys = [random_key, random_key1, random_key2, random_key3]
|
|
results = region.get_multi(keys)
|
|
# should return NO_VALUE as key does not exist in cache
|
|
self.assertEqual(api.NO_VALUE, results[0])
|
|
self.assertEqual("dummyValue1", results[1])
|
|
self.assertEqual("", results[2])
|
|
self.assertEqual("dummyValue3", results[3])
|
|
|
|
def test_backend_multi_set_should_update_existing(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
random_key = uuid.uuid4().hex
|
|
random_key1 = uuid.uuid4().hex
|
|
random_key2 = uuid.uuid4().hex
|
|
random_key3 = uuid.uuid4().hex
|
|
mapping = {random_key1: 'dummyValue1',
|
|
random_key2: 'dummyValue2',
|
|
random_key3: 'dummyValue3'}
|
|
region.set_multi(mapping)
|
|
# should return NO_VALUE as key does not exist in cache
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key))
|
|
self.assertEqual("dummyValue1", region.get(random_key1))
|
|
self.assertEqual("dummyValue2", region.get(random_key2))
|
|
self.assertEqual("dummyValue3", region.get(random_key3))
|
|
|
|
mapping = {random_key1: 'dummyValue4',
|
|
random_key2: 'dummyValue5'}
|
|
region.set_multi(mapping)
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key))
|
|
self.assertEqual("dummyValue4", region.get(random_key1))
|
|
self.assertEqual("dummyValue5", region.get(random_key2))
|
|
self.assertEqual("dummyValue3", region.get(random_key3))
|
|
|
|
def test_backend_multi_set_get_with_blanks_none(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
random_key = uuid.uuid4().hex
|
|
random_key1 = uuid.uuid4().hex
|
|
random_key2 = uuid.uuid4().hex
|
|
random_key3 = uuid.uuid4().hex
|
|
random_key4 = uuid.uuid4().hex
|
|
mapping = {random_key1: 'dummyValue1',
|
|
random_key2: None,
|
|
random_key3: '',
|
|
random_key4: 'dummyValue4'}
|
|
region.set_multi(mapping)
|
|
# should return NO_VALUE as key does not exist in cache
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key))
|
|
self.assertEqual("dummyValue1", region.get(random_key1))
|
|
self.assertIsNone(region.get(random_key2))
|
|
self.assertEqual("", region.get(random_key3))
|
|
self.assertEqual("dummyValue4", region.get(random_key4))
|
|
|
|
keys = [random_key, random_key1, random_key2, random_key3, random_key4]
|
|
results = region.get_multi(keys)
|
|
|
|
# should return NO_VALUE as key does not exist in cache
|
|
self.assertEqual(api.NO_VALUE, results[0])
|
|
self.assertEqual("dummyValue1", results[1])
|
|
self.assertIsNone(results[2])
|
|
self.assertEqual("", results[3])
|
|
self.assertEqual("dummyValue4", results[4])
|
|
|
|
mapping = {random_key1: 'dummyValue5',
|
|
random_key2: 'dummyValue6'}
|
|
region.set_multi(mapping)
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key))
|
|
self.assertEqual("dummyValue5", region.get(random_key1))
|
|
self.assertEqual("dummyValue6", region.get(random_key2))
|
|
self.assertEqual("", region.get(random_key3))
|
|
|
|
def test_backend_delete_data(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, "dummyValue")
|
|
self.assertEqual("dummyValue", region.get(random_key))
|
|
|
|
region.delete(random_key)
|
|
# should return NO_VALUE as key no longer exists in cache
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key))
|
|
|
|
def test_backend_multi_delete_data(self):
|
|
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
random_key = uuid.uuid4().hex
|
|
random_key1 = uuid.uuid4().hex
|
|
random_key2 = uuid.uuid4().hex
|
|
random_key3 = uuid.uuid4().hex
|
|
mapping = {random_key1: 'dummyValue1',
|
|
random_key2: 'dummyValue2',
|
|
random_key3: 'dummyValue3'}
|
|
region.set_multi(mapping)
|
|
# should return NO_VALUE as key does not exist in cache
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key))
|
|
self.assertEqual("dummyValue1", region.get(random_key1))
|
|
self.assertEqual("dummyValue2", region.get(random_key2))
|
|
self.assertEqual("dummyValue3", region.get(random_key3))
|
|
self.assertEqual(api.NO_VALUE, region.get("InvalidKey"))
|
|
|
|
keys = mapping.keys()
|
|
|
|
region.delete_multi(keys)
|
|
|
|
self.assertEqual(api.NO_VALUE, region.get("InvalidKey"))
|
|
# should return NO_VALUE as keys no longer exist in cache
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key1))
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key2))
|
|
self.assertEqual(api.NO_VALUE, region.get(random_key3))
|
|
|
|
def test_additional_crud_method_arguments_support(self):
|
|
"""Additional arguments should works across find/insert/update."""
|
|
|
|
self.arguments['wtimeout'] = 30000
|
|
self.arguments['j'] = True
|
|
self.arguments['continue_on_error'] = True
|
|
self.arguments['secondary_acceptable_latency_ms'] = 60
|
|
region = dp_region.make_region().configure(
|
|
'keystone.cache.mongo',
|
|
arguments=self.arguments
|
|
)
|
|
|
|
# There is no proxy so can access MongoCacheBackend directly
|
|
api_methargs = region.backend.api.meth_kwargs
|
|
self.assertEqual(api_methargs['wtimeout'], 30000)
|
|
self.assertEqual(api_methargs['j'], True)
|
|
self.assertEqual(api_methargs['continue_on_error'], True)
|
|
self.assertEqual(api_methargs['secondary_acceptable_latency_ms'], 60)
|
|
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, "dummyValue1")
|
|
self.assertEqual("dummyValue1", region.get(random_key))
|
|
|
|
region.set(random_key, "dummyValue2")
|
|
self.assertEqual("dummyValue2", region.get(random_key))
|
|
|
|
random_key = uuid.uuid4().hex
|
|
region.set(random_key, "dummyValue3")
|
|
self.assertEqual("dummyValue3", region.get(random_key))
|