deb-murano/murano/tests/unit/test_engine.py
Kirill Zaitsev c8ca2ef72e Safely encode yaql expressions to support unicode expressions
Before unicode in yaql would cause a UnicodeEncodeError.
Now YaqlExpression should behave better with unicode input.

Change-Id: I3bbb018d7bd78cbf66c4190ef4c0b7d7e3baa03c
Closes-Bug: #1361169
2015-03-31 09:34:01 +00:00

206 lines
7.1 KiB
Python

# coding: utf-8
# Copyright (c) 2014 Mirantis Inc.
#
# 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 re
import mock
import yaql
import murano.dsl.helpers as helpers
import murano.dsl.namespace_resolver as ns_resolver
import murano.dsl.yaql_expression as yaql_expression
from murano.tests.unit import base
ROOT_CLASS = 'io.murano.Object'
class TestNamespaceResolving(base.MuranoTestCase):
def setUp(self):
super(TestNamespaceResolving, self).setUp()
def test_fails_w_empty_name(self):
resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
self.assertRaises(ValueError, resolver.resolve_name, None)
def test_fails_w_unknown_prefix(self):
resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
name = 'unknown_prefix:example.murano'
self.assertRaises(KeyError, resolver.resolve_name, name)
def test_fails_w_prefix_wo_name(self):
resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
name = 'sys:'
self.assertRaises(NameError, resolver.resolve_name, name)
def test_fails_w_excessive_prefix(self):
ns = {'sys': 'com.example.murano.system'}
resolver = ns_resolver.NamespaceResolver(ns)
invalid_name = 'sys:excessive_ns:muranoResource'
self.assertRaises(NameError, resolver.resolve_name, invalid_name)
def test_cuts_empty_prefix(self):
resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
# name without prefix delimiter
name = 'some.arbitrary.name'
resolved_name = resolver.resolve_name(':' + name)
self.assertEqual(name, resolved_name)
def test_resolves_specified_ns_prefix(self):
ns = {'sys': 'com.example.murano.system'}
resolver = ns_resolver.NamespaceResolver(ns)
short_name, full_name = 'sys:File', 'com.example.murano.system.File'
resolved_name = resolver.resolve_name(short_name)
self.assertEqual(full_name, resolved_name)
def test_resolves_current_ns(self):
resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
short_name, full_name = 'Resource', 'com.example.murano.Resource'
resolved_name = resolver.resolve_name(short_name)
self.assertEqual(full_name, resolved_name)
def test_resolves_explicit_base(self):
resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
resolved_name = resolver.resolve_name('Resource', relative='com.base')
self.assertEqual('com.base.Resource', resolved_name)
def test_resolves_explicit_base_w_empty_namespaces(self):
resolver = ns_resolver.NamespaceResolver({})
resolved_name = resolver.resolve_name('File', 'com.base')
self.assertEqual('com.base.File', resolved_name)
def test_resolves_w_empty_namespaces(self):
resolver = ns_resolver.NamespaceResolver({})
resolved_name = resolver.resolve_name('Resource')
self.assertEqual('Resource', resolved_name)
class Bunch(object):
def __init__(self, **kwargs):
super(Bunch, self).__init__()
for key, value in kwargs.iteritems():
setattr(self, key, value)
class TestHelperFunctions(base.MuranoTestCase):
def setUp(self):
super(TestHelperFunctions, self).setUp()
def test_generate_id(self):
generated_id = helpers.generate_id()
self.assertTrue(re.match(r'[a-z0-9]{32}', generated_id))
def test_evaluate(self):
yaql_value = mock.Mock(spec=yaql_expression.YaqlExpression,
evaluate=lambda context: 'atom')
complex_value = {yaql_value: ['some', (1, yaql_value), lambda: 'hi!'],
'sample': [yaql_value, xrange(5)]}
complex_literal = {'atom': ['some', (1, 'atom'), 'hi!'],
'sample': ['atom', [0, 1, 2, 3, 4]]}
# tuple(evaluate(list)) transformation adds + 1
complex_literal_depth = 3 + 1
context = yaql.create_context(False)
evaluated_value = helpers.evaluate(yaql_value, context, 1)
non_evaluated_value = helpers.evaluate(yaql_value, context, 0)
evaluated_complex_value = helpers.evaluate(complex_value, context)
non_evaluated_complex_value = helpers.evaluate(
complex_value, context, complex_literal_depth)
self.assertEqual('atom', evaluated_value)
self.assertNotEqual('atom', non_evaluated_value)
self.assertEqual(complex_literal, evaluated_complex_value)
self.assertNotEqual(complex_literal, non_evaluated_complex_value)
def test_needs_evaluation(self):
testee = helpers.needs_evaluation
parsed_expr = yaql.parse("string")
yaql_expr = yaql_expression.YaqlExpression("string")
self.assertTrue(testee(parsed_expr))
self.assertTrue(testee(yaql_expr))
self.assertTrue(testee({yaql_expr: 1}))
self.assertTrue(testee({'label': yaql_expr}))
self.assertTrue(testee([yaql_expr]))
class TestYaqlExpression(base.MuranoTestCase):
def setUp(self):
super(TestYaqlExpression, self).setUp()
def test_expression(self):
yaql_expr = yaql_expression.YaqlExpression('string')
self.assertEqual('string', yaql_expr.expression)
def test_unicode_expression(self):
yaql_expr = yaql_expression.YaqlExpression(u"'yaql ♥ unicode'")
self.assertEqual(u"'yaql ♥ unicode'".encode('utf-8'),
yaql_expr.expression)
def test_unicode_expression_expression(self):
yaql_expr = yaql_expression.YaqlExpression(u"'yaql ♥ unicode'")
yaql_expr2 = yaql_expression.YaqlExpression(yaql_expr)
self.assertEqual(u"'yaql ♥ unicode'".encode('utf-8'),
yaql_expr2.expression)
def test_evaluate_calls(self):
string = 'string'
expected_calls = [mock.call(string),
mock.call().evaluate(context=None)]
with mock.patch('yaql.parse') as mock_parse:
yaql_expr = yaql_expression.YaqlExpression(string)
yaql_expr.evaluate()
self.assertEqual(expected_calls, mock_parse.mock_calls)
def test_match_returns(self):
expr = yaql_expression.YaqlExpression('string')
with mock.patch('yaql.parse'):
self.assertTrue(expr.match('$some'))
self.assertTrue(expr.match('$.someMore'))
with mock.patch('yaql.parse') as parse_mock:
parse_mock.side_effect = yaql.exceptions.YaqlGrammarException
self.assertFalse(expr.match(''))
with mock.patch('yaql.parse') as parse_mock:
parse_mock.side_effect = yaql.exceptions.YaqlLexicalException
self.assertFalse(expr.match(''))