90 lines
3.6 KiB
Python
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)))
|