salt/tests/unit/utils/test_json.py
Erik Johnson 879c557264
Use decorators for temp files/dirs in test suite
This adds a new decorator which creates a temporary directory and cleans
it after the test completes. It also modifies an existing decorator for
creating temporary files so that it accepts arguments, which will be
passed through to salt.utils.files.mkstemp().
2018-04-18 19:46:29 -05:00

146 lines
5.9 KiB
Python

# -*- coding: utf-8 -*-
'''
Tests for salt.utils.json
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import textwrap
# Import Salt Testing libs
from tests.support.helpers import with_tempfile
from tests.support.mock import patch, MagicMock, NO_MOCK, NO_MOCK_REASON
from tests.support.unit import TestCase, LOREM_IPSUM, skipIf
# Import Salt libs
import salt.utils.files
import salt.utils.json
import salt.utils.platform
import salt.utils.stringutils
from salt.ext import six
class JSONTestCase(TestCase):
data = {
'спам': 'яйца',
'list': [1, 2, 'three'],
'dict': {'subdict': {'спам': 'яйца'}},
'True': False,
'float': 1.5,
'None': None,
}
serialized = salt.utils.stringutils.to_str(
'{"None": null, "True": false, "dict": {"subdict": {"спам": "яйца"}}, "float": 1.5, "list": [1, 2, "three"], "спам": "яйца"}'
)
serialized_indent4 = salt.utils.stringutils.to_str(textwrap.dedent('''\
{
"None": null,
"True": false,
"dict": {
"subdict": {
"спам": "яйца"
}
},
"float": 1.5,
"list": [
1,
2,
"three"
],
"спам": "яйца"
}'''))
def test_find_json(self):
test_sample_json = '''
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
'''
expected_ret = {'glossary': {'GlossDiv': {'GlossList': {'GlossEntry': {
'GlossDef': {'GlossSeeAlso': ['GML', 'XML'],
'para': 'A meta-markup language, used to create markup languages such as DocBook.'},
'GlossSee': 'markup', 'Acronym': 'SGML', 'GlossTerm': 'Standard Generalized Markup Language',
'SortAs': 'SGML',
'Abbrev': 'ISO 8879:1986', 'ID': 'SGML'}}, 'title': 'S'}, 'title': 'example glossary'}}
# First test the valid JSON
ret = salt.utils.json.find_json(test_sample_json)
self.assertDictEqual(ret, expected_ret)
# Now pre-pend some garbage and re-test
garbage_prepend_json = '{0}{1}'.format(LOREM_IPSUM, test_sample_json)
ret = salt.utils.json.find_json(garbage_prepend_json)
self.assertDictEqual(ret, expected_ret)
# Test to see if a ValueError is raised if no JSON is passed in
self.assertRaises(ValueError, salt.utils.json.find_json, LOREM_IPSUM)
@skipIf(salt.utils.platform.is_windows(), 'skip until we figure out what to do about decoding unicode on windows')
@skipIf(not six.PY2, 'Test only needed on Python 2')
@skipIf(NO_MOCK, NO_MOCK_REASON)
def test_find_json_unicode_splitlines(self):
'''
Tests a case in salt-ssh where a unicode string is split into a list of
str types by .splitlines().
'''
raw = '{"foo": "öäü"}'
mock_split = MagicMock(return_value=[raw.encode('utf8')])
with patch.object(salt.utils.json, '__split', mock_split):
ret = salt.utils.json.find_json(raw)
self.assertEqual(ret, {'foo': 'öäü'})
def test_dumps_loads(self):
'''
Test dumping to and loading from a string
'''
# Dump with no indentation
ret = salt.utils.json.dumps(self.data, sort_keys=True)
# Make sure the result is as expected
self.assertEqual(ret, self.serialized)
# Loading it should be equal to the original data
self.assertEqual(salt.utils.json.loads(ret), self.data)
# Dump with 4 spaces of indentation
ret = salt.utils.json.dumps(self.data, sort_keys=True, indent=4)
# Make sure the result is as expected. Note that in Python 2, dumping
# results in trailing whitespace on lines ending in a comma. So, for a
# proper comparison, we will have to run rstrip on each line of the
# return and then stitch it back together.
ret = str('\n').join([x.rstrip() for x in ret.splitlines()]) # future lint: disable=blacklisted-function
self.assertEqual(ret, self.serialized_indent4)
# Loading it should be equal to the original data
self.assertEqual(salt.utils.json.loads(ret), self.data)
@with_tempfile()
def test_dump_load(self, json_out):
'''
Test dumping to and loading from a file handle
'''
with salt.utils.files.fopen(json_out, 'w') as fp_:
salt.utils.json.dump(self.data, fp_)
with salt.utils.files.fopen(json_out, 'r') as fp_:
ret = salt.utils.json.load(fp_)
# Loading should be equal to the original data
self.assertEqual(ret, self.data)