Commit d357f531 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Fix serializer unittests

Commit d22b2999

 broke the serializer unittests with certain
versions of simplejson. This patch removes sort_keys again
and implements a slightly more efficient way of detecting
simplejson functionality. The serializer unittests no longer
use a partially broken mock, but rather a function to convert all
tuples to lists before comparing.
Signed-off-by: default avatarMichael Hanselmann <>
Reviewed-by: default avatarGuido Trotter <>
parent aeb0c953
......@@ -36,16 +36,41 @@ try:
except ImportError:
import sha as sha1
# Check whether the simplejson module supports indentation
simplejson.dumps(1, indent=_JSON_INDENT)
except TypeError:
_RE_EOLSP = re.compile('[ \t]+$', re.MULTILINE)
def _GetJsonDumpers():
"""Returns two JSON functions to serialize data.
@rtype: (callable, callable)
@return: The function to generate a compact form of JSON and another one to
generate a more readable, indented form of JSON (if supported)
plain_dump = simplejson.dumps
# Check whether the simplejson module supports indentation
simplejson.dumps(1, indent=_JSON_INDENT)
except TypeError:
# Indentation not supported
indent_dump = plain_dump
# Indentation supported
indent_dump = lambda data: simplejson.dumps(data, indent=_JSON_INDENT)
assert callable(plain_dump)
assert callable(indent_dump)
return (plain_dump, indent_dump)
(_DumpJson, _DumpJsonIndent) = _GetJsonDumpers()
def DumpJson(data, indent=True):
"""Serialize a given object.
......@@ -55,14 +80,15 @@ def DumpJson(data, indent=True):
@return: the string representation of data
if not indent or _JSON_INDENT is None:
txt = simplejson.dumps(data)
if indent:
fn = _DumpJsonIndent
txt = simplejson.dumps(data, indent=_JSON_INDENT, sort_keys=True)
fn = _DumpJson
txt = _RE_EOLSP.sub("", txt)
txt = _RE_EOLSP.sub("", fn(data))
if not txt.endswith('\n'):
txt += '\n'
return txt
......@@ -27,16 +27,10 @@ import unittest
from ganeti import serializer
from ganeti import errors
import testutils
class SimplejsonMock(object):
def dumps(self, data, indent=None):
return repr(data)
def loads(self, data):
return eval(data)
class TestSerializer(unittest.TestCase):
class TestSerializer(testutils.GanetiTestCase):
"""Serializer tests"""
......@@ -44,15 +38,23 @@ class TestSerializer(unittest.TestCase):
[1, 2, 3],
(1, 2, 3),
{ 1: 2, "foo": "bar", },
{ "1": 2, "foo": "bar", },
["abc", 1, 2, 3, 999,
"a1": ("Hello", "World"),
"a2": "This is only a test",
"a3": None,
"foo": "bar",
def setUp(self):
self._orig_simplejson = serializer.simplejson
serializer.simplejson = SimplejsonMock()
def tearDown(self):
serializer.simplejson = self._orig_simplejson
def _TestSerializer(self, dump_fn, load_fn):
for data in self._TESTDATA:
self.assertEqualValues(load_fn(dump_fn(data)), data)
def testGeneric(self):
return self._TestSerializer(serializer.Dump, serializer.Load)
......@@ -65,20 +67,17 @@ class TestSerializer(unittest.TestCase):
DumpSigned = serializer.DumpSigned
for data in self._TESTDATA:
self.assertEqual(LoadSigned(DumpSigned(data, "mykey"), "mykey"),
(data, ''))
DumpSigned(data, "myprivatekey", "mysalt"),
"myprivatekey"), (data, "mysalt"))
self.assertEqualValues(LoadSigned(DumpSigned(data, "mykey"), "mykey"),
(data, ''))
self.assertEqualValues(LoadSigned(DumpSigned(data, "myprivatekey",
(data, "mysalt"))
self.assertRaises(errors.SignatureError, serializer.LoadSigned,
serializer.DumpSigned("test", "myprivatekey"),
def _TestSerializer(self, dump_fn, load_fn):
for data in self._TESTDATA:
self.failUnlessEqual(load_fn(dump_fn(data)), data)
if __name__ == '__main__':
......@@ -75,6 +75,16 @@ class GanetiTestCase(unittest.TestCase):
actual_mode = stat.S_IMODE(st.st_mode)
self.assertEqual(actual_mode, expected_mode)
def assertEqualValues(self, first, second, msg=None):
"""Compares two values whether they're equal.
Tuples are automatically converted to lists before comparing.
return self.assertEqual(UnifyValueType(first),
def _TestDataFilename(name):
"""Returns the filename of a given test data file.
......@@ -97,7 +107,6 @@ class GanetiTestCase(unittest.TestCase):
proper test file name.
return utils.ReadFile(cls._TestDataFilename(name))
def _CreateTempFile(self):
......@@ -111,3 +120,19 @@ class GanetiTestCase(unittest.TestCase):
return fname
def UnifyValueType(data):
"""Converts all tuples into lists.
This is useful for unittests where an external library doesn't keep types.
if isinstance(data, (tuple, list)):
return [UnifyValueType(i) for i in data]
elif isinstance(data, dict):
return dict([(UnifyValueType(key), UnifyValueType(value))
for (key, value) in data.iteritems()])
return data
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment