# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You 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 pytest import sqlalchemy from aria.storage import ( ModelStorage, sql_mapi ) from aria import modeling from aria.modeling.exceptions import ValueFormatException from ..storage import ( release_sqlite_storage, init_inmemory_model_storage ) from . import MockModel from ..mock import ( models, context as mock_context ) @pytest.fixture def storage(): base_storage = ModelStorage(sql_mapi.SQLAlchemyModelAPI, initiator=init_inmemory_model_storage) base_storage.register(MockModel) yield base_storage release_sqlite_storage(base_storage) @pytest.fixture(scope='module', autouse=True) def module_cleanup(): modeling.models.aria_declarative_base.metadata.remove(MockModel.__table__) # pylint: disable=no-member @pytest.fixture def context(tmpdir): ctx = mock_context.simple(str(tmpdir)) yield ctx release_sqlite_storage(ctx.model) def test_inner_dict_update(storage): inner_dict = {'inner_value': 1} mock_model = MockModel(model_dict={'inner_dict': inner_dict, 'value': 0}) storage.mock_model.put(mock_model) storage_mm = storage.mock_model.get(mock_model.id) assert storage_mm == mock_model storage_mm.model_dict['inner_dict']['inner_value'] = 2 storage_mm.model_dict['value'] = -1 storage.mock_model.update(storage_mm) storage_mm = storage.mock_model.get(storage_mm.id) assert storage_mm.model_dict['inner_dict']['inner_value'] == 2 assert storage_mm.model_dict['value'] == -1 def test_inner_list_update(storage): mock_model = MockModel(model_list=[0, [1]]) storage.mock_model.put(mock_model) storage_mm = storage.mock_model.get(mock_model.id) assert storage_mm == mock_model storage_mm.model_list[1][0] = 'new_inner_value' storage_mm.model_list[0] = 'new_value' storage.mock_model.update(storage_mm) storage_mm = storage.mock_model.get(storage_mm.id) assert storage_mm.model_list[1][0] == 'new_inner_value' assert storage_mm.model_list[0] == 'new_value' def test_model_to_dict(context): service = context.service service = service.to_dict() expected_keys = [ 'description', 'created_at', 'updated_at' ] for expected_key in expected_keys: assert expected_key in service def test_relationship_model_ordering(context): service = context.model.service.get_by_name(models.SERVICE_NAME) source_node = context.model.node.get_by_name(models.DEPENDENT_NODE_NAME) target_node = context.model.node.get_by_name(models.DEPENDENCY_NODE_NAME) new_node_template = modeling.models.NodeTemplate( name='new_node_template', type=source_node.type, service_template=service.service_template ) new_node = modeling.models.Node( name='new_node', type=source_node.type, service=service, version=None, node_template=new_node_template, state=modeling.models.Node.INITIAL, ) source_node.outbound_relationships.append(modeling.models.Relationship( source_node=source_node, target_node=new_node, )) new_node.outbound_relationships.append(modeling.models.Relationship( # pylint: disable=no-member source_node=new_node, target_node=target_node, )) context.model.node_template.put(new_node_template) context.model.node.put(new_node) context.model.node.refresh(source_node) context.model.node.refresh(target_node) def flip_and_assert(node, direction): """ Reversed the order of relationships and assert effects took place. :param node: the node instance to operate on :param direction: the type of relationships to flip (inbound/outbound) :return: """ assert direction in ('inbound', 'outbound') def get_relationships(): return getattr(node, direction + '_relationships') relationships = get_relationships() assert len(relationships) == 2 reversed_relationship = list(reversed(relationships)) assert relationships != reversed_relationship relationships[:] = reversed_relationship context.model.node.update(node) assert get_relationships() == reversed_relationship flip_and_assert(source_node, 'outbound') flip_and_assert(target_node, 'inbound') class StrictClass(modeling.models.aria_declarative_base, modeling.mixins.ModelMixin): __tablename__ = 'strict_class' strict_dict = sqlalchemy.Column(modeling.types.StrictDict(basestring, basestring)) strict_list = sqlalchemy.Column(modeling.types.StrictList(basestring)) def test_strict_dict(): strict_class = StrictClass() def assert_strict(sc): with pytest.raises(ValueFormatException): sc.strict_dict = {'key': 1} with pytest.raises(ValueFormatException): sc.strict_dict = {1: 'value'} with pytest.raises(ValueFormatException): sc.strict_dict = {1: 1} assert_strict(strict_class) strict_class.strict_dict = {'key': 'value'} assert strict_class.strict_dict == {'key': 'value'} assert_strict(strict_class) with pytest.raises(ValueFormatException): strict_class.strict_dict['key'] = 1 with pytest.raises(ValueFormatException): strict_class.strict_dict[1] = 'value' with pytest.raises(ValueFormatException): strict_class.strict_dict[1] = 1 def test_strict_list(): strict_class = StrictClass() def assert_strict(sc): with pytest.raises(ValueFormatException): sc.strict_list = [1] assert_strict(strict_class) strict_class.strict_list = ['item'] assert strict_class.strict_list == ['item'] assert_strict(strict_class) with pytest.raises(ValueFormatException): strict_class.strict_list[0] = 1