
There were three main issues in the code from refstack repository that
were preventing refstack jobs from working:
1) Improper handling of sessions in the database API.
2) PEP8 job was failing because of outdated version of flake8.
3) The new version of cryptography library doesn't support signer() and
verifier() functions.
Issue #1 was solved by using the get_session() function as a context
manager instead of using session.begin() as a context manager. Using
session.begin() as a context manager does not ensure that the session
will be closed at the end of the context (see "Opening and Closing
a Session" and "Framing out a begin / commit / rollback block"
here [1]).
Issue #2 was solved by updating the libraries in
test-requirements.txt file. This change also forces flake8 to ignore
some pep8 errors (similar to the ones ignored in tempest project).
Issue #3 was solved by using the sign() and verify() functions instead
of verifier() and signer() functions [2].
Related Taiga issues:
- https://tree.taiga.io/project/openstack-interop-working-group/issue/77
- https://tree.taiga.io/project/openstack-interop-working-group/issue/79
[1] https://docs.sqlalchemy.org/en/14/orm/session_basics.html
[2] e71c0df301
Change-Id: If98670475b371d1ece7c877a0eea3158f6c1b3f5
874 lines
36 KiB
Python
874 lines
36 KiB
Python
# Copyright (c) 2015 Mirantis, Inc.
|
|
# All 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.
|
|
|
|
"""Tests for database."""
|
|
|
|
import base64
|
|
import hashlib
|
|
from unittest import mock
|
|
|
|
from oslo_config import fixture as config_fixture
|
|
from oslotest import base
|
|
import sqlalchemy.orm
|
|
|
|
from refstack.api import constants as api_const
|
|
from refstack import db
|
|
from refstack.db.sqlalchemy import api
|
|
from refstack.db.sqlalchemy import models
|
|
|
|
|
|
class DBAPITestCase(base.BaseTestCase):
|
|
"""Test case for database API."""
|
|
|
|
@mock.patch.object(api, 'store_test_results')
|
|
def test_store_test_results(self, mock_store_test_results):
|
|
db.store_test_results('fake_results')
|
|
mock_store_test_results.assert_called_once_with('fake_results')
|
|
|
|
@mock.patch.object(api, 'get_test_result')
|
|
def test_get_test_result(self, mock_get_test_result):
|
|
db.get_test_result(12345)
|
|
mock_get_test_result.assert_called_once_with(12345, allowed_keys=None)
|
|
|
|
@mock.patch.object(api, 'get_test_results')
|
|
def test_get_test_results(self, mock_get_test_results):
|
|
db.get_test_results(12345)
|
|
mock_get_test_results.assert_called_once_with(12345)
|
|
|
|
@mock.patch.object(api, 'get_test_result_records')
|
|
def test_get_test_result_records(self, mock_db):
|
|
filters = mock.Mock()
|
|
db.get_test_result_records(1, 2, filters)
|
|
mock_db.assert_called_once_with(1, 2, filters)
|
|
|
|
@mock.patch.object(api, 'get_test_result_records_count')
|
|
def test_get_test_result_records_count(self, mock_db):
|
|
filters = mock.Mock()
|
|
db.get_test_result_records_count(filters)
|
|
mock_db.assert_called_once_with(filters)
|
|
|
|
@mock.patch.object(api, 'user_get')
|
|
def test_user_get(self, mock_db):
|
|
user_openid = 'user@example.com'
|
|
db.user_get(user_openid)
|
|
mock_db.assert_called_once_with(user_openid)
|
|
|
|
@mock.patch.object(api, 'user_save')
|
|
def test_user_save(self, mock_db):
|
|
user_info = 'user@example.com'
|
|
db.user_save(user_info)
|
|
mock_db.assert_called_once_with(user_info)
|
|
|
|
|
|
class DBHelpersTestCase(base.BaseTestCase):
|
|
"""Test case for database backend helpers."""
|
|
|
|
@mock.patch.object(api, '_create_facade_lazily')
|
|
def test_get_engine(self, mock_create_facade):
|
|
facade = mock_create_facade.return_value
|
|
facade.get_engine = mock.Mock(return_value='fake_engine')
|
|
|
|
result = api.get_engine()
|
|
mock_create_facade.assert_called_once_with()
|
|
facade.get_engine.assert_called_once_with()
|
|
self.assertEqual(result, 'fake_engine')
|
|
|
|
@mock.patch.object(api, '_create_facade_lazily')
|
|
def test_get_session(self, mock_create_facade):
|
|
facade = mock_create_facade.return_value
|
|
facade.get_session = mock.Mock(return_value='fake_session')
|
|
|
|
fake_kwargs = {'foo': 'bar'}
|
|
result = api.get_session(**fake_kwargs)
|
|
|
|
mock_create_facade.assert_called_once_with()
|
|
facade.get_session.assert_called_once_with(**fake_kwargs)
|
|
self.assertEqual(result, 'fake_session')
|
|
|
|
@mock.patch('oslo_db.sqlalchemy.session.EngineFacade.from_config')
|
|
def test_create_facade_lazily(self, session):
|
|
session.return_value = 'fake_session'
|
|
result = api._create_facade_lazily()
|
|
self.assertEqual(result, 'fake_session')
|
|
|
|
|
|
class DBBackendTestCase(base.BaseTestCase):
|
|
"""Test case for database backend."""
|
|
|
|
def setUp(self):
|
|
super(DBBackendTestCase, self).setUp()
|
|
self.config_fixture = config_fixture.Config()
|
|
self.CONF = self.useFixture(self.config_fixture).conf
|
|
|
|
def test_to_dict(self):
|
|
fake_query_result = mock.Mock()
|
|
fake_query_result.keys.return_value = ('fake_id',)
|
|
fake_query_result.index = 1
|
|
fake_query_result.fake_id = 12345
|
|
self.assertEqual({'fake_id': 12345}, api._to_dict(fake_query_result))
|
|
|
|
fake_query_result_list = [fake_query_result]
|
|
self.assertEqual([{'fake_id': 12345}],
|
|
api._to_dict(fake_query_result_list))
|
|
|
|
fake_query = mock.Mock(spec=sqlalchemy.orm.Query)
|
|
fake_query.all.return_value = fake_query_result
|
|
self.assertEqual({'fake_id': 12345}, api._to_dict(fake_query))
|
|
|
|
fake_model = mock.Mock(spec=models.RefStackBase)
|
|
fake_model.default_allowed_keys = ('fake_id', 'meta',
|
|
'child', 'childs')
|
|
fake_child = mock.Mock(spec=models.RefStackBase)
|
|
fake_child.iteritems.return_value = {'child_id': 42}.items()
|
|
fake_child.default_allowed_keys = ('child_id',)
|
|
fake_child.metadata_keys = {}
|
|
actuall_dict = {'fake_id': 12345,
|
|
'meta': [{'meta_key': 'answer',
|
|
'value': 42}],
|
|
'child': fake_child,
|
|
'childs': [fake_child]}
|
|
fake_model.iteritems.return_value = actuall_dict.items()
|
|
fake_model.metadata_keys = {'meta': {'key': 'meta_key',
|
|
'value': 'value'}}
|
|
|
|
self.assertEqual({'fake_id': 12345,
|
|
'meta': {'answer': 42},
|
|
'child': {'child_id': 42},
|
|
'childs': [{'child_id': 42}]},
|
|
api._to_dict(fake_model))
|
|
|
|
fake_model = mock.Mock(spec=models.RefStackBase)
|
|
fake_model.default_allowed_keys = ('meta', 'beta')
|
|
fake_model.metadata_keys = {}
|
|
fake_model.iteritems.return_value = {'meta': 1, 'beta': 2}.items()
|
|
self.assertEqual([{'meta': 1}],
|
|
api._to_dict([fake_model], allowed_keys=('meta')))
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.TestResults')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Test')
|
|
@mock.patch('refstack.db.sqlalchemy.models.TestMeta')
|
|
@mock.patch('uuid.uuid4')
|
|
def test_store_test_results(self, mock_uuid, mock_test_meta, mock_test,
|
|
mock_test_result, mock_get_session):
|
|
fake_tests_result = {
|
|
'cpid': 'foo',
|
|
'duration_seconds': 10,
|
|
'results': [
|
|
{'name': 'tempest.some.test'},
|
|
{'name': 'tempest.test', 'uid': '12345678'}
|
|
],
|
|
'meta': {'answer': 42}
|
|
}
|
|
_id = 12345
|
|
|
|
mock_uuid.return_value = _id
|
|
test = mock_test.return_value
|
|
test.save = mock.Mock()
|
|
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
|
|
test_result = mock_test_result.return_value
|
|
test_result.save = mock.Mock()
|
|
|
|
test_id = api.store_test_results(fake_tests_result)
|
|
|
|
mock_test.assert_called_once_with()
|
|
mock_get_session.assert_called_once_with()
|
|
test.save.assert_called_once_with(session)
|
|
|
|
self.assertEqual(test_id, str(_id))
|
|
self.assertEqual(test.cpid, fake_tests_result['cpid'])
|
|
self.assertEqual(test.duration_seconds,
|
|
fake_tests_result['duration_seconds'])
|
|
self.assertEqual(mock_test_result.call_count,
|
|
len(fake_tests_result['results']))
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Test')
|
|
@mock.patch.object(api, '_to_dict', side_effect=lambda x, *args: x)
|
|
def test_get_test_result(self, mock_to_dict, mock_test, mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
|
|
session.query = mock.Mock()
|
|
query = session.query.return_value
|
|
query.filter_by = mock.Mock()
|
|
filter_by = query.filter_by.return_value
|
|
mock_result = 'fake_test_info'
|
|
filter_by.first = mock.Mock(return_value=mock_result)
|
|
test_id = 'fake_id'
|
|
actual_result = api.get_test_result(test_id)
|
|
|
|
mock_get_session.assert_called_once_with()
|
|
session.query.assert_called_once_with(mock_test)
|
|
query.filter_by.assert_called_once_with(id=test_id)
|
|
filter_by.first.assert_called_once_with()
|
|
self.assertEqual(mock_result, actual_result)
|
|
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
session.query = mock.Mock()
|
|
query = session.query.return_value
|
|
query.filter_by.return_value.first.return_value = None
|
|
self.assertRaises(api.NotFound, api.get_test_result, 'fake_id')
|
|
|
|
@mock.patch('refstack.db.sqlalchemy.api.models')
|
|
@mock.patch.object(api, 'get_session')
|
|
def test_delete_test_result(self, mock_get_session, mock_models):
|
|
test_query = mock.Mock()
|
|
test_meta_query = mock.Mock()
|
|
test_results_query = mock.Mock()
|
|
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
|
|
session.query = mock.Mock(side_effect={
|
|
mock_models.Test: test_query,
|
|
mock_models.TestMeta: test_meta_query,
|
|
mock_models.TestResults: test_results_query
|
|
}.get)
|
|
|
|
db.delete_test_result('fake_id')
|
|
|
|
test_query.filter_by.return_value.first\
|
|
.assert_called_once_with()
|
|
test_meta_query.filter_by.return_value.delete\
|
|
.assert_called_once_with()
|
|
test_results_query.filter_by.return_value.delete\
|
|
.assert_called_once_with()
|
|
session.delete.assert_called_once_with(
|
|
test_query.filter_by.return_value.first.return_value)
|
|
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
|
|
session.query.return_value\
|
|
.filter_by.return_value\
|
|
.first.return_value = None
|
|
|
|
self.assertRaises(api.NotFound, db.delete_test_result, 'fake_id')
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch.object(api, '_to_dict', side_effect=lambda x: x)
|
|
def test_update_test_result(self, mock_to_dict, mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
mock_test = mock.Mock()
|
|
session.query.return_value.filter_by.return_value\
|
|
.first.return_value = mock_test
|
|
|
|
test_info = {'product_version_id': '123'}
|
|
api.update_test_result(test_info)
|
|
|
|
mock_get_session.assert_called_once_with()
|
|
mock_test.save.assert_called_once_with(session=session)
|
|
|
|
@mock.patch('refstack.db.sqlalchemy.api.models')
|
|
@mock.patch.object(api, 'get_session')
|
|
def test_get_test_result_meta_key(self, mock_get_session, mock_models):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
session.query.return_value\
|
|
.filter_by.return_value\
|
|
.filter_by.return_value\
|
|
.first.return_value = mock.Mock(value=42)
|
|
self.assertEqual(
|
|
42, db.get_test_result_meta_key('fake_id', 'fake_key'))
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
session.query.return_value\
|
|
.filter_by.return_value\
|
|
.filter_by.return_value\
|
|
.first.return_value = None
|
|
self.assertEqual(24, db.get_test_result_meta_key(
|
|
'fake_id', 'fake_key', 24))
|
|
|
|
@mock.patch('refstack.db.sqlalchemy.api.models')
|
|
@mock.patch.object(api, 'get_session')
|
|
def test_save_test_result_meta_item(self, mock_get_session, mock_models):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
mock_meta_item = mock.Mock()
|
|
session.query.return_value\
|
|
.filter_by.return_value\
|
|
.filter_by.return_value\
|
|
.first.return_value = mock_meta_item
|
|
db.save_test_result_meta_item('fake_id', 'fake_key', 42)
|
|
self.assertEqual('fake_id', mock_meta_item.test_id)
|
|
self.assertEqual('fake_key', mock_meta_item.meta_key)
|
|
self.assertEqual(42, mock_meta_item.value)
|
|
mock_meta_item.save.assert_called_once_with(session)
|
|
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
session.query.return_value\
|
|
.filter_by.return_value\
|
|
.filter_by.return_value\
|
|
.first.return_value = None
|
|
mock_meta_item = mock.Mock()
|
|
mock_models.TestMeta.return_value = mock_meta_item
|
|
db.save_test_result_meta_item('fake_id', 'fake_key', 42)
|
|
self.assertEqual('fake_id', mock_meta_item.test_id)
|
|
self.assertEqual('fake_key', mock_meta_item.meta_key)
|
|
self.assertEqual(42, mock_meta_item.value)
|
|
|
|
@mock.patch('refstack.db.sqlalchemy.api.models')
|
|
@mock.patch.object(api, 'get_session')
|
|
def test_delete_test_result_meta_item(self, mock_get_session, mock_models):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
mock_meta_item = mock.Mock()
|
|
session.query.return_value\
|
|
.filter_by.return_value\
|
|
.filter_by.return_value\
|
|
.first.return_value = mock_meta_item
|
|
db.delete_test_result_meta_item('fake_id', 'fake_key')
|
|
session.delete.assert_called_once_with(mock_meta_item)
|
|
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
session.query.return_value\
|
|
.filter_by.return_value\
|
|
.filter_by.return_value\
|
|
.first.return_value = None
|
|
self.assertRaises(db.NotFound,
|
|
db.delete_test_result_meta_item,
|
|
'fake_id', 'fake_key')
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.TestResults')
|
|
def test_get_test_results(self, mock_test_result, mock_get_session):
|
|
mock_test_result.name = mock.Mock()
|
|
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
session.query = mock.Mock()
|
|
query = session.query.return_value
|
|
query.filter_by = mock.Mock()
|
|
filter_by = query.filter_by.return_value
|
|
mock_result = 'fake_test_results'
|
|
expected_result = ['fake_test_results']
|
|
filter_by.all = mock.Mock(return_value=[mock_result])
|
|
|
|
test_id = 'fake_id'
|
|
actual_result = api.get_test_results(test_id)
|
|
|
|
mock_get_session.assert_called_once_with()
|
|
session.query.assert_called_once_with(mock_test_result)
|
|
query.filter_by.assert_called_once_with(test_id=test_id)
|
|
filter_by.all.assert_called_once_with()
|
|
self.assertEqual(expected_result, actual_result)
|
|
|
|
@mock.patch('refstack.db.sqlalchemy.models.Test')
|
|
@mock.patch('refstack.db.sqlalchemy.models.TestMeta')
|
|
def test_apply_filters_for_query_unsigned(self, mock_meta,
|
|
mock_test):
|
|
query = mock.Mock()
|
|
mock_test.created_at = str()
|
|
mock_meta.test_id = str()
|
|
|
|
filters = {
|
|
api_const.START_DATE: 'fake1',
|
|
api_const.END_DATE: 'fake2',
|
|
api_const.CPID: 'fake3'
|
|
}
|
|
|
|
unsigned_query = (query
|
|
.filter.return_value
|
|
.filter.return_value
|
|
.filter.return_value)
|
|
|
|
unsigned_query.session.query.return_value.filter_by.side_effect = (
|
|
'signed_results_query', 'shared_results_query'
|
|
)
|
|
|
|
result = api._apply_filters_for_query(query, filters)
|
|
|
|
query.filter.assert_called_once_with(mock_test.created_at >=
|
|
filters[api_const.START_DATE])
|
|
|
|
query = query.filter.return_value
|
|
query.filter.assert_called_once_with(mock_test.created_at <=
|
|
filters[api_const.END_DATE])
|
|
|
|
query = query.filter.return_value
|
|
query.filter.assert_called_once_with(mock_test.cpid ==
|
|
filters[api_const.CPID])
|
|
|
|
unsigned_query.session.query.assert_has_calls((
|
|
mock.call(mock_meta.test_id),
|
|
mock.call().filter_by(meta_key='user'),
|
|
mock.call(mock_meta.test_id),
|
|
mock.call().filter_by(meta_key='shared'),
|
|
))
|
|
unsigned_query.filter.assert_has_calls((
|
|
mock.call(mock_test.id.notin_.return_value),
|
|
mock.call(mock_test.id.in_.return_value),
|
|
mock.call().union(unsigned_query.filter.return_value)
|
|
))
|
|
filtered_query = unsigned_query.filter.return_value.union.return_value
|
|
|
|
self.assertEqual(result, filtered_query)
|
|
|
|
@mock.patch('refstack.db.sqlalchemy.models.Test')
|
|
@mock.patch('refstack.db.sqlalchemy.models.TestMeta')
|
|
def test_apply_filters_for_query_signed(self, mock_meta,
|
|
mock_test):
|
|
query = mock.Mock()
|
|
mock_test.created_at = str()
|
|
mock_meta.test_id = str()
|
|
mock_meta.meta_key = 'user'
|
|
mock_meta.value = 'test-openid'
|
|
|
|
filters = {
|
|
api_const.START_DATE: 'fake1',
|
|
api_const.END_DATE: 'fake2',
|
|
api_const.CPID: 'fake3',
|
|
api_const.USER_PUBKEYS: ['fake_pk'],
|
|
api_const.SIGNED: 'true',
|
|
api_const.OPENID: 'test-openid'
|
|
}
|
|
|
|
signed_query = (query
|
|
.filter.return_value
|
|
.filter.return_value
|
|
.filter.return_value)
|
|
|
|
result = api._apply_filters_for_query(query, filters)
|
|
|
|
signed_query.join.assert_called_once_with(mock_test.meta)
|
|
signed_query = signed_query.join.return_value
|
|
signed_query.filter.assert_called_once_with(
|
|
mock_meta.meta_key == api_const.USER
|
|
)
|
|
signed_query = signed_query.filter.return_value
|
|
signed_query.filter.assert_called_once_with(
|
|
mock_meta.value == filters[api_const.OPENID]
|
|
)
|
|
filtered_query = signed_query.filter.return_value
|
|
self.assertEqual(result, filtered_query)
|
|
|
|
@mock.patch.object(api, '_apply_filters_for_query')
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Test')
|
|
def test_get_test_result_records(self, mock_model,
|
|
mock_get_session,
|
|
mock_apply):
|
|
|
|
per_page = 9000
|
|
filters = {
|
|
api_const.START_DATE: 'fake1',
|
|
api_const.END_DATE: 'fake2',
|
|
api_const.CPID: 'fake3'
|
|
}
|
|
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
|
|
first_query = session.query.return_value
|
|
second_query = mock_apply.return_value
|
|
ordered_query = second_query.order_by.return_value
|
|
query_with_offset = ordered_query.offset.return_value
|
|
query_with_offset.limit.return_value.all.return_value = 'fake_uploads'
|
|
|
|
result = api.get_test_result_records(2, per_page, filters)
|
|
|
|
mock_get_session.assert_called_once_with()
|
|
session.query.assert_called_once_with(mock_model)
|
|
mock_apply.assert_called_once_with(first_query, filters)
|
|
second_query.order_by.\
|
|
assert_called_once_with(mock_model.created_at.desc())
|
|
|
|
self.assertEqual(result, 'fake_uploads')
|
|
ordered_query.offset.assert_called_once_with(per_page)
|
|
query_with_offset.limit.assert_called_once_with(per_page)
|
|
|
|
@mock.patch.object(api, '_apply_filters_for_query')
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Test')
|
|
def test_get_test_result_records_count(self, mock_model,
|
|
mock_get_session,
|
|
mock_apply):
|
|
|
|
filters = mock.Mock()
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
query = session.query.return_value
|
|
apply_result = mock_apply.return_value
|
|
apply_result.count.return_value = 999
|
|
|
|
result = api.get_test_result_records_count(filters)
|
|
self.assertEqual(result, 999)
|
|
|
|
session.query.assert_called_once_with(mock_model.id)
|
|
mock_apply.assert_called_once_with(query, filters)
|
|
apply_result.count.assert_called_once_with()
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.User')
|
|
def test_user_get(self, mock_model, mock_get_session):
|
|
user_openid = 'user@example.com'
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
query = session.query.return_value
|
|
filtered = query.filter_by.return_value
|
|
user = filtered.first.return_value
|
|
|
|
result = api.user_get(user_openid)
|
|
self.assertEqual(result, user)
|
|
|
|
session.query.assert_called_once_with(mock_model)
|
|
query.filter_by.assert_called_once_with(openid=user_openid)
|
|
filtered.first.assert_called_once_with()
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.User')
|
|
def test_user_get_none(self, mock_model, mock_get_session):
|
|
user_openid = 'user@example.com'
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
query = session.query.return_value
|
|
filtered = query.filter_by.return_value
|
|
filtered.first.return_value = None
|
|
self.assertRaises(api.NotFound, api.user_get, user_openid)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.User')
|
|
@mock.patch.object(api, 'user_get', side_effect=api.NotFound('User'))
|
|
def test_user_update_or_create(self, mock_get_user, mock_model,
|
|
mock_get_session):
|
|
user_info = {'openid': 'user@example.com'}
|
|
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
|
|
user = mock_model.return_value
|
|
result = api.user_save(user_info)
|
|
self.assertEqual(result, user)
|
|
|
|
mock_model.assert_called_once_with()
|
|
mock_get_session.assert_called_once_with()
|
|
user.save.assert_called_once_with(session=session)
|
|
user.update.assert_called_once_with(user_info)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.PubKey')
|
|
def test_get_pubkey(self, mock_model, mock_get_session):
|
|
key = 'AAAAB3Nz'
|
|
khash = hashlib.md5(base64.b64decode(key.encode('ascii'))).hexdigest()
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
query = session.query.return_value
|
|
filtered = query.filter_by.return_value
|
|
|
|
# Test no key match.
|
|
filtered.all.return_value = []
|
|
result = api.get_pubkey(key)
|
|
self.assertIsNone(result)
|
|
|
|
session.query.assert_called_once_with(mock_model)
|
|
query.filter_by.assert_called_once_with(md5_hash=khash)
|
|
filtered.all.assert_called_once_with()
|
|
|
|
# Test only one key match.
|
|
filtered.all.return_value = [{'pubkey': key, 'md5_hash': khash}]
|
|
result = api.get_pubkey(key)
|
|
self.assertEqual({'pubkey': key, 'md5_hash': khash}, result)
|
|
|
|
# Test multiple keys with same md5 hash.
|
|
filtered.all.return_value = [{'pubkey': 'key2', 'md5_hash': khash},
|
|
{'pubkey': key, 'md5_hash': khash}]
|
|
result = api.get_pubkey(key)
|
|
self.assertEqual({'pubkey': key, 'md5_hash': khash}, result)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.api.models')
|
|
def test_store_pubkey(self, mock_models, mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
pubkey_info = {
|
|
'openid': 'fake_id',
|
|
'format': 'ssh-rsa',
|
|
'pubkey': 'cHV0aW4gaHVpbG8=',
|
|
'comment': 'comment'
|
|
}
|
|
mock_pubkey = mock.Mock()
|
|
mock_pubkey.id = 42
|
|
mock_models.PubKey.return_value = mock_pubkey
|
|
session.query.return_value\
|
|
.filter_by.return_value\
|
|
.filter_by.return_value\
|
|
.all.return_value = None
|
|
self.assertEqual(42, db.store_pubkey(pubkey_info))
|
|
self.assertEqual('fake_id', mock_pubkey.openid)
|
|
self.assertEqual('ssh-rsa', mock_pubkey.format)
|
|
self.assertEqual('cHV0aW4gaHVpbG8=', mock_pubkey.pubkey)
|
|
self.assertEqual(
|
|
hashlib.md5(
|
|
base64.b64decode('cHV0aW4gaHVpbG8='.encode('ascii'))
|
|
).hexdigest(),
|
|
'3b30cd2bdac1eeb7e92dfc983bf5f943'
|
|
)
|
|
mock_pubkey.save.assert_called_once_with(session)
|
|
session.query.return_value\
|
|
.filter_by.return_value\
|
|
.filter_by.return_value\
|
|
.all.return_value = mock_pubkey
|
|
self.assertRaises(db.Duplication,
|
|
db.store_pubkey, pubkey_info)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.api.models')
|
|
def test_delete_pubkey(self, mock_models, mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
|
|
db.delete_pubkey('key_id')
|
|
key = session\
|
|
.query.return_value\
|
|
.filter_by.return_value\
|
|
.first.return_value
|
|
session.query.assert_called_once_with(mock_models.PubKey)
|
|
session.query.return_value.filter_by.assert_called_once_with(
|
|
id='key_id')
|
|
session.delete.assert_called_once_with(key)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.api.models')
|
|
@mock.patch.object(api, '_to_dict', side_effect=lambda x: x)
|
|
def test_get_user_pubkeys(self, mock_to_dict, mock_models,
|
|
mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
actual_keys = db.get_user_pubkeys('user_id')
|
|
keys = session \
|
|
.query.return_value \
|
|
.filter_by.return_value \
|
|
.all.return_value
|
|
session.query.assert_called_once_with(mock_models.PubKey)
|
|
session.query.return_value.filter_by.assert_called_once_with(
|
|
openid='user_id')
|
|
self.assertEqual(keys, actual_keys)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.UserToGroup')
|
|
def test_add_user_to_group(self, mock_model, mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
api.add_user_to_group('user-123', 'GUID', 'user-321')
|
|
|
|
mock_model.assert_called_once_with()
|
|
mock_get_session.assert_called_once_with()
|
|
mock_model.return_value.save.assert_called_once_with(session=session)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.api.models')
|
|
def test_remove_user_from_group(self, mock_models, mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
db.remove_user_from_group('user-123', 'GUID')
|
|
|
|
session.query.assert_called_once_with(mock_models.UserToGroup)
|
|
session.query.return_value.filter_by.assert_has_calls((
|
|
mock.call(user_openid='user-123'),
|
|
mock.call().filter_by(group_id='GUID'),
|
|
mock.call().filter_by().delete(synchronize_session=False)))
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Organization')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Group')
|
|
@mock.patch('refstack.db.sqlalchemy.models.UserToGroup')
|
|
@mock.patch.object(api, '_to_dict', side_effect=lambda x: x)
|
|
def test_organization_add(self, mock_to_dict, mock_model_user_to_group,
|
|
mock_model_group, mock_model_organization,
|
|
mock_get_session):
|
|
|
|
organization_info = {'name': 'a', 'description': 'b', 'type': 1}
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
organization = mock_model_organization.return_value
|
|
result = api.add_organization(organization_info, 'user-123')
|
|
self.assertEqual(result, organization)
|
|
|
|
group = mock_model_group.return_value
|
|
self.assertIsNotNone(group.id)
|
|
self.assertIsNotNone(organization.id)
|
|
self.assertIsNotNone(organization.group_id)
|
|
|
|
mock_model_organization.assert_called_once_with()
|
|
mock_model_group.assert_called_once_with()
|
|
mock_model_user_to_group.assert_called_once_with()
|
|
mock_get_session.assert_called_once_with()
|
|
organization.save.assert_called_once_with(session=session)
|
|
group.save.assert_called_once_with(session=session)
|
|
user_to_group = mock_model_user_to_group.return_value
|
|
user_to_group.save.assert_called_once_with(session=session)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Product')
|
|
@mock.patch('refstack.db.sqlalchemy.models.ProductVersion')
|
|
@mock.patch.object(api, '_to_dict', side_effect=lambda x: x)
|
|
def test_product_add(self, mock_to_dict, mock_version,
|
|
mock_product, mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
version = mock_version.return_value
|
|
product = mock_product.return_value
|
|
product_info = {'product_ref_id': 'hash_or_guid', 'name': 'a',
|
|
'organization_id': 'GUID0', 'type': 0,
|
|
'product_type': 0}
|
|
result = api.add_product(product_info, 'user-123')
|
|
self.assertEqual(result, product)
|
|
|
|
self.assertIsNotNone(product.id)
|
|
self.assertIsNotNone(version.id)
|
|
self.assertIsNotNone(version.product_id)
|
|
self.assertIsNone(version.version)
|
|
|
|
mock_get_session.assert_called_once_with()
|
|
product.save.assert_called_once_with(session=session)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Product')
|
|
def test_incomplete_product_add(self, mock_product, mock_get_session):
|
|
product_info = {}
|
|
self.assertRaises(KeyError, api.add_product, product_info, 'u')
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Product.save')
|
|
def test_product_update(self, mock_product_save, mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
query = session.query.return_value
|
|
filtered = query.filter_by.return_value
|
|
product = models.Product()
|
|
product.id = '123'
|
|
filtered.first.return_value = product
|
|
|
|
product_info = {'product_ref_id': '098', 'name': 'a',
|
|
'description': 'b', 'creator_openid': 'abc',
|
|
'organization_id': '1', 'type': 0, 'product_type': 0,
|
|
'id': '123'}
|
|
api.update_product(product_info)
|
|
|
|
self.assertEqual('098', product.product_ref_id)
|
|
self.assertIsNone(product.created_by_user)
|
|
self.assertIsNone(product.organization_id)
|
|
self.assertIsNone(product.type)
|
|
self.assertIsNone(product.product_type)
|
|
|
|
mock_get_session.assert_called_once_with()
|
|
mock_product_save.assert_called_once_with(session=session)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Organization')
|
|
@mock.patch.object(api, '_to_dict', side_effect=lambda x, allowed_keys: x)
|
|
def test_organization_get(self, mock_to_dict, mock_model,
|
|
mock_get_session):
|
|
organization_id = 12345
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
query = session.query.return_value
|
|
filtered = query.filter_by.return_value
|
|
organization = filtered.first.return_value
|
|
|
|
result = api.get_organization(organization_id)
|
|
self.assertEqual(result, organization)
|
|
|
|
session.query.assert_called_once_with(mock_model)
|
|
query.filter_by.assert_called_once_with(id=organization_id)
|
|
filtered.first.assert_called_once_with()
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Product')
|
|
@mock.patch.object(api, '_to_dict', side_effect=lambda x, allowed_keys: x)
|
|
def test_product_get(self, mock_to_dict, mock_model, mock_get_session):
|
|
_id = 12345
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
query = session.query.return_value
|
|
filtered = query.filter_by.return_value
|
|
product = filtered.first.return_value
|
|
|
|
result = api.get_product(_id)
|
|
self.assertEqual(result, product)
|
|
|
|
session.query.assert_called_once_with(mock_model)
|
|
query.filter_by.assert_called_once_with(id=_id)
|
|
filtered.first.assert_called_once_with()
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.api.models')
|
|
def test_product_delete(self, mock_models, mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
db.delete_product('product_id')
|
|
|
|
session.query.return_value.filter_by.assert_has_calls((
|
|
mock.call(product_id='product_id'),
|
|
mock.call().delete(synchronize_session=False)))
|
|
session.query.return_value.filter_by.assert_has_calls((
|
|
mock.call(id='product_id'),
|
|
mock.call().delete(synchronize_session=False)))
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.api.models')
|
|
def test_get_organization_users(self, mock_models, mock_get_session):
|
|
organization_id = 12345
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
query = session.query.return_value
|
|
filtered = query.filter_by.return_value
|
|
filtered.first.return_value.group_id = 'foo'
|
|
|
|
join = query.join.return_value
|
|
|
|
fake_user = models.User()
|
|
fake_user.openid = 'foobar'
|
|
fake_user.fullname = 'Foo Bar'
|
|
fake_user.email = 'foo@bar.com'
|
|
join.filter.return_value = [(mock.Mock(), fake_user)]
|
|
|
|
result = api.get_organization_users(organization_id)
|
|
expected = {'foobar': {'openid': 'foobar',
|
|
'fullname': 'Foo Bar',
|
|
'email': 'foo@bar.com'}}
|
|
self.assertEqual(expected, result)
|
|
|
|
session.query.assert_any_call(mock_models.Organization.group_id)
|
|
query.filter_by.assert_called_once_with(id=organization_id)
|
|
session.query.assert_any_call(mock_models.UserToGroup,
|
|
mock_models.User)
|
|
|
|
@mock.patch.object(api, 'get_session')
|
|
@mock.patch('refstack.db.sqlalchemy.models.Organization')
|
|
@mock.patch.object(api, '_to_dict', side_effect=lambda x, allowed_keys: x)
|
|
def test_organizations_get(self, mock_to_dict, mock_model,
|
|
mock_get_session):
|
|
session = mock.Mock()
|
|
mock_get_session.return_value.__enter__.return_value = session
|
|
query = session.query.return_value
|
|
ordered = query.order_by.return_value
|
|
organizations = ordered.all.return_value
|
|
|
|
result = api.get_organizations()
|
|
self.assertEqual(organizations, result)
|
|
|
|
session.query.assert_called_once_with(mock_model)
|
|
query.order_by.assert_called_once_with(mock_model.created_at.desc())
|
|
ordered.all.assert_called_once_with()
|