deckhand/deckhand/tests/unit/common/test_utils.py

90 lines
3.6 KiB
Python

# Copyright 2018 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 jsonpath_ng
import mock
from testtools.matchers import Equals
from testtools.matchers import MatchesAny
from deckhand.common import utils
from deckhand.tests.unit import base as test_base
class TestJSONPathReplace(test_base.DeckhandTestCase):
"""Validate that JSONPath replace function works."""
def test_jsonpath_replace_creates_object(self):
path = ".values.endpoints.admin"
expected = {'values': {'endpoints': {'admin': 'foo'}}}
result = utils.jsonpath_replace({}, 'foo', path)
self.assertEqual(expected, result)
def test_jsonpath_replace_with_array_index_creates_array(self):
path = ".values.endpoints[0].admin"
expected = {'values': {'endpoints': [{'admin': 'foo'}]}}
result = utils.jsonpath_replace({}, 'foo', path)
self.assertEqual(expected, result)
path = ".values.endpoints[1].admin"
expected = {'values': {'endpoints': [{}, {'admin': 'foo'}]}}
result = utils.jsonpath_replace({}, 'foo', path)
self.assertEqual(expected, result)
def test_jsonpath_replace_with_numeric_value_creates_object(self):
path = ".values.endpoints0.admin"
expected = {'values': {'endpoints0': {'admin': 'foo'}}}
result = utils.jsonpath_replace({}, 'foo', path)
self.assertEqual(expected, result)
class TestJSONPathUtilsCaching(test_base.DeckhandTestCase):
"""Validate that JSONPath caching works."""
def setUp(self):
super(TestJSONPathUtilsCaching, self).setUp()
self.jsonpath_call_count = 0
def fake_parse(value):
self.jsonpath_call_count += 1
return jsonpath_ng.parse(value)
self.fake_jsonpath_ng = fake_parse
def test_jsonpath_parse_replace_cache(self):
"""Validate caching for both parsing and replacing functions."""
path = ".values.endpoints.admin"
expected = {'values': {'endpoints': {'admin': 'foo'}}}
# Mock jsonpath_ng to return a monkey-patched parse function that
# keeps track of call count and yet calls the actual function.
with mock.patch.object(utils, 'jsonpath_ng', # noqa: H210
parse=self.fake_jsonpath_ng):
# Though this is called 3 times, the cached function should only
# be called once, with the cache returning the cached value early.
for _ in range(3):
result = utils.jsonpath_replace({}, 'foo', path)
self.assertEqual(expected, result)
# Though this is called 3 times, the cached function should only
# be called once, with the cache returning the cached value early.
for _ in range(3):
result = utils.jsonpath_parse(expected, path)
self.assertEqual('foo', result)
# Assert that the actual function was called <= 1 times. (Allow for 0
# in case CI jobs clash.)
self.assertThat(
self.jsonpath_call_count, MatchesAny(Equals(0), Equals(1)))