Test and DB API changes.

This commit is contained in:
Felipe Monteiro 2017-07-29 23:37:25 +01:00
parent b44392bcb4
commit 2d36f866a1
4 changed files with 141 additions and 136 deletions

View File

@ -114,53 +114,56 @@ def documents_create(documents, session=None):
return created_docs return created_docs
def document_create(values, session=None): def documents_create(values_list, session=None):
"""Create a document.""" """Create a document."""
values = values.copy() values_list = copy.deepcopy(values_list)
values['_metadata'] = values.pop('metadata')
values['name'] = values['_metadata']['name']
session = session or get_session() session = session or get_session()
filters = models.Document.UNIQUE_CONSTRAINTS filters = models.Document.UNIQUE_CONSTRAINTS
try:
existing_document = document_get(
raw_dict=True,
**{c: values[c] for c in filters if c != 'revision_id'})
except db_exception.DBError:
# Ignore bad data at this point. Allow creation to bubble up the error
# related to bad data.
existing_document = None
created_document = {} do_create = False
documents_created = []
def _document_changed(): def _document_changed(existing_document):
# The document has changed if at least one value in ``values`` differs. # The document has changed if at least one value in ``values`` differs.
for key, val in values.items(): for key, val in values.items():
if val != existing_document[key]: if val != existing_document[key]:
return True return True
return False return False
def _document_create(): def _document_create(values):
document = models.Document() document = models.Document()
with session.begin(): with session.begin():
document.update(values) document.update(values)
document.save(session=session) document.save(session=session)
return document.to_dict() return document.to_dict()
if existing_document: for values in values_list:
# Only generate a new revision and entirely new document if anything values['_metadata'] = values.pop('metadata')
# was changed. values['name'] = values['_metadata']['name']
if _document_changed():
revision = revision_create_parent(existing_document)
values['revision_id'] = revision['id']
created_document = _document_create()
revision_update_child(existing_document, created_document)
else:
revision = revision_create()
values['revision_id'] = revision['id']
created_document = _document_create()
return created_document try:
existing_document = document_get(
raw_dict=True,
**{c: values[c] for c in filters if c != 'revision_id'})
except db_exception.DBError:
# Ignore bad data at this point. Allow creation to bubble up the
# error related to bad data.
existing_document = None
if not existing_document:
do_create = True
elif existing_document and _document_changed(existing_document):
do_create = True
if do_create:
revision = revision_create()
for values in values_list:
values['revision_id'] = revision['id']
doc = _document_create(values)
documents_created.append(doc)
return documents_created
def document_get(session=None, raw_dict=False, **filters): def document_get(session=None, raw_dict=False, **filters):

View File

@ -0,0 +1,53 @@
# Copyright 2017 AT&T Intellectual Property. All other rights reserved.
#
# 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 random
import uuid
def rand_uuid():
"""Generate a random UUID string
:return: a random UUID (e.g. '1dc12c7d-60eb-4b61-a7a2-17cf210155b6')
:rtype: string
"""
return uuidutils.generate_uuid()
def rand_uuid_hex():
"""Generate a random UUID hex string
:return: a random UUID (e.g. '0b98cf96d90447bda4b46f31aeb1508c')
:rtype: string
"""
return uuid.uuid4().hex
def rand_name(name='', prefix='tempest'):
"""Generate a random name that includes a random number
:param str name: The name that you want to include
:param str prefix: The prefix that you want to include
:return: a random name. The format is
'<prefix>-<name>-<random number>'.
(e.g. 'prefixfoo-namebar-154876201')
:rtype: string
"""
randbits = str(random.randint(1, 0x7fffffff))
rand_name = randbits
if name:
rand_name = name + '-' + rand_name
if prefix:
rand_name = prefix + '-' + rand_name
return rand_name

View File

@ -36,6 +36,9 @@ class DeckhandTestCase(testtools.TestCase):
CONF.set_override(name, override, group) CONF.set_override(name, override, group)
self.addCleanup(CONF.clear_override, name, group) self.addCleanup(CONF.clear_override, name, group)
def assertEmpty(self, list):
self.assertEqual(0, len(list))
class DeckhandWithDBTestCase(DeckhandTestCase): class DeckhandWithDBTestCase(DeckhandTestCase):

View File

@ -19,6 +19,7 @@ import testtools
from testtools import matchers from testtools import matchers
from deckhand.db.sqlalchemy import api as db_api from deckhand.db.sqlalchemy import api as db_api
from deckhand.tests import test_utils
from deckhand.tests.unit import base from deckhand.tests.unit import base
BASE_EXPECTED_FIELDS = ("created_at", "updated_at", "deleted_at", "deleted") BASE_EXPECTED_FIELDS = ("created_at", "updated_at", "deleted_at", "deleted")
@ -32,19 +33,28 @@ class DocumentFixture(object):
@staticmethod @staticmethod
def get_minimal_fixture(**kwargs): def get_minimal_fixture(**kwargs):
fixture = {'data': 'fake document data', fixture = {'data': test_utils.rand_name('data'),
'metadata': {'name': 'fake metadata'}, 'metadata': {'name': test_utils.rand_name('name')},
'schema': 'deckhand/v1'} 'schema': test_utils.rand_name('schema', prefix='deckhand')}
fixture.update(kwargs) fixture.update(kwargs)
return fixture return fixture
@staticmethod
def get_minimal_multi_fixture(count=2, **kwargs):
return [DocumentFixture.get_minimal_fixture(**kwargs)
for _ in range(count)]
class TestDocumentsApi(base.DeckhandWithDBTestCase): class TestDocumentsApi(base.DeckhandWithDBTestCase):
def _create_document(self, payload): def _create_documents(self, payload):
doc = db_api.document_create(payload) if not isinstance(payload, list):
self._validate_document(expected=payload, actual=doc) payload = [payload]
return doc
docs = db_api.documents_create(payload)
for idx, doc in enumerate(docs):
self._validate_document(expected=payload[idx], actual=doc)
return docs
def _get_document(self, **fields): def _get_document(self, **fields):
doc = db_api.document_get(**fields) doc = db_api.document_get(**fields)
@ -107,115 +117,51 @@ class TestDocumentsApi(base.DeckhandWithDBTestCase):
def test_create_and_get_document(self): def test_create_and_get_document(self):
payload = DocumentFixture.get_minimal_fixture() payload = DocumentFixture.get_minimal_fixture()
document = self._create_document(payload) documents = self._create_documents(payload)
retrieved_document = self._get_document(id=document['id'])
self.assertEqual(document, retrieved_document) self.assertIsInstance(documents, list)
self.assertEqual(1, len(documents))
for document in documents:
retrieved_document = self._get_document(id=document['id'])
self.assertEqual(document, retrieved_document)
def test_create_document_again_with_no_changes(self):
payload = DocumentFixture.get_minimal_fixture()
self._create_documents(payload)
documents = self._create_documents(payload)
self.assertIsInstance(documents, list)
self.assertEmpty(documents)
def test_create_document_and_get_revision(self): def test_create_document_and_get_revision(self):
payload = DocumentFixture.get_minimal_fixture() payload = DocumentFixture.get_minimal_fixture()
document = self._create_document(payload) documents = self._create_documents(payload)
revision = self._get_revision(document['revision_id']) self.assertIsInstance(documents, list)
self._validate_revision(revision) self.assertEqual(1, len(documents))
self.assertEqual(document['revision_id'], revision['id'])
def test_create_and_update_document(self): for document in documents:
""" revision = self._get_revision(document['revision_id'])
Check that the following relationship is true: self._validate_revision(revision)
self.assertEqual(document['revision_id'], revision['id'])
parent_document --> parent_revision
| ^
(has child) (has parent)
v |
child_document --> child_revision
"""
child_payload = DocumentFixture.get_minimal_fixture()
child_document = self._create_document(child_payload)
parent_payload = DocumentFixture.get_minimal_fixture()
parent_payload['data'] = 'fake updated document data'
parent_document = self._create_document(parent_payload)
# Validate that the new document was created.
self.assertEqual('fake updated document data', parent_document['data'])
self.assertNotEqual(child_document['id'], parent_document['id'])
# Validate that the parent document has a different revision and
# that the revisions and document links are correct.
child_revision = self._get_revision(child_document['revision_id'])
parent_revision = self._get_revision(parent_document['revision_id'])
self._validate_revision_connections(
parent_document, parent_revision, child_document, child_revision)
def test_create_and_update_document_schema(self):
"""
Check that the following relationship is true:
parent_document --> parent_revision
child_document --> child_revision
"schema" is unique so changing it results in a new document being
created.
"""
child_payload = DocumentFixture.get_minimal_fixture()
child_document = self._create_document(child_payload)
parent_payload = DocumentFixture.get_minimal_fixture()
parent_payload['schema'] = 'deckhand/v2'
parent_document = self._create_document(parent_payload)
# Validate that the new document was created.
self.assertEqual('deckhand/v2', parent_document['schema'])
self.assertNotEqual(child_document['id'], parent_document['id'])
# Validate that the parent document has a different revision and
# that the revisions and document links are correct.
child_revision = self._get_revision(child_document['revision_id'])
parent_revision = self._get_revision(parent_document['revision_id'])
self._validate_revision_connections(
parent_document, parent_revision, child_document, child_revision,
False)
def test_create_and_update_document_metadata_name(self):
"""
Check that the following relationship is true:
parent_document --> parent_revision
child_document --> child_revision
"metadata.name" is unique so changing it results in a new document
being created.
"""
child_payload = DocumentFixture.get_minimal_fixture()
child_document = self._create_document(child_payload)
parent_payload = DocumentFixture.get_minimal_fixture()
parent_payload['metadata'] = {'name': 'fake updated metadata'}
parent_document = self._create_document(parent_payload)
# Validate that the new document was created.
self.assertEqual({'name': 'fake updated metadata'},
parent_document['metadata'])
self.assertNotEqual(child_document['id'], parent_document['id'])
# Validate that the parent document has a different revision and
# that the revisions and document links are correct.
child_revision = self._get_revision(child_document['revision_id'])
parent_revision = self._get_revision(parent_document['revision_id'])
self._validate_revision_connections(
parent_document, parent_revision, child_document, child_revision,
False)
def test_get_documents_by_revision_id(self): def test_get_documents_by_revision_id(self):
payload = DocumentFixture.get_minimal_fixture() payload = DocumentFixture.get_minimal_fixture()
document = self._create_document(payload) documents = self._create_documents(payload)
revision = self._get_revision(document['revision_id']) revision = self._get_revision(documents[0]['revision_id'])
self.assertEqual(1, len(revision['documents'])) self.assertEqual(1, len(revision['documents']))
self.assertEqual(document, revision['documents'][0]) self.assertEqual(documents[0], revision['documents'][0])
def test_get_multiple_documents_by_revision_id(self): def test_get_multiple_documents_by_revision_id(self):
# TODO payload = DocumentFixture.get_minimal_multi_fixture(count=3)
documents = self._create_documents(payload)
self.assertIsInstance(documents, list)
self.assertEqual(3, len(documents))
for document in documents:
revision = self._get_revision(document['revision_id'])
self._validate_revision(revision)
self.assertEqual(document['revision_id'], revision['id'])