Skip to content

Commit

Permalink
Add more tests on the Encoder/Decoder classes
Browse files Browse the repository at this point in the history
  • Loading branch information
lelit committed Aug 17, 2017
1 parent 8d78fef commit 9e34c01
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 40 deletions.
103 changes: 75 additions & 28 deletions tests/test_base_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,29 @@

@pytest.mark.unit
@pytest.mark.parametrize(
'value', [
'value', (
'A', 'cruel\x00world', 1, -1, 2.3,
{'foo': 'bar', '\x00': 'issue57', 'issue57': '\x00'},
[1, 2, 'a', 1.2, {'foo': 'bar'},],
sys.maxsize, sys.maxsize**2
])
def test_base_values(value):
dumped = rj.dumps(value)
loaded = rj.loads(dumped)
sys.maxsize, sys.maxsize**2,
))
@pytest.mark.parametrize('dumps,loads', ((rj.dumps, rj.loads), (rj.Encoder(), rj.Decoder())))
def test_base_values(value, dumps, loads):
dumped = dumps(value)
loaded = loads(dumped)
assert loaded == value and type(loaded) is type(value)


@pytest.mark.unit
def test_bytes_value():
dumped = rj.dumps(b'cruel\x00world')
@pytest.mark.parametrize('dumps', (rj.dumps, rj.Encoder()))
def test_bytes_value(dumps):
dumped = dumps(b'cruel\x00world')
assert dumped == r'"cruel\u0000world"'


@pytest.mark.unit
def test_larger_structure():
@pytest.mark.parametrize('dumps,loads', ((rj.dumps, rj.loads), (rj.Encoder(), rj.Decoder())))
def test_larger_structure(dumps, loads):
value = {
'words': """
Lorem ipsum dolor sit amet, consectetur adipiscing
Expand All @@ -41,9 +44,8 @@ def test_larger_structure():
'float': 100999.123456
}

dumped = rj.dumps(value)
loaded = rj.loads(dumped)

dumped = dumps(value)
loaded = loads(dumped)
assert loaded == value


Expand All @@ -64,41 +66,70 @@ def as_complex(dct):


@pytest.mark.unit
def test_default():
def test_end_object():
class ComplexDecoder(rj.Decoder):
def end_object(self, dct):
if '__complex__' in dct:
return complex(dct['real'], dct['imag'])

return dct

loads = ComplexDecoder()
result = loads('{"__complex__": true, "real": 1, "imag": 2}')
assert result == (1+2j)


@pytest.mark.unit
def test_dumps_default():
def encode_complex(obj):
if isinstance(obj, complex):
return [obj.real, obj.imag]

raise TypeError(repr(obj) + " is not JSON serializable")

result = rj.dumps(2 + 1j, default=encode_complex)
assert result == '[2.0,1.0]'


@pytest.mark.unit
def test_doubles():
def test_encoder_default():
class ComplexEncoder(rj.Encoder):
def default(self, obj):
if isinstance(obj, complex):
return [obj.real, obj.imag]
raise TypeError(repr(obj) + " is not JSON serializable")

dumps = ComplexEncoder()
result = dumps(2 + 1j)
assert result == '[2.0,1.0]'


@pytest.mark.unit
@pytest.mark.parametrize('dumps,loads', ((rj.dumps, rj.loads), (rj.Encoder(), rj.Decoder())))
def test_doubles(dumps, loads):
for x in range(100000):
d = sys.maxsize * random.random()
dumped = rj.dumps(d)
loaded = rj.loads(dumped)
dumped = dumps(d)
loaded = loads(dumped)
assert loaded == d


@pytest.mark.unit
def test_unicode():
@pytest.mark.parametrize('dumps,loads', ((rj.dumps, rj.loads), (rj.Encoder(), rj.Decoder())))
def test_unicode(dumps, loads):
arabic='بينهم ان يكون مسلما رشيدا عاقلا ًوابنا شرعيا لابوين عمانيين'
chinese='本站所提供的資料和服務都不收費,因此網站所需要的資金全來自廣告及捐款。若您願意捐款補助'

for text in [arabic, chinese]:
dumped = rj.dumps(text)
loaded = rj.loads(dumped)
for text in (arabic, chinese):
dumped = dumps(text)
loaded = loads(dumped)
assert text == loaded


@pytest.mark.unit
def test_serialize_sets():
def test_serialize_sets_dumps():
def default_iterable(obj):
return list(obj)
if isinstance(obj, set):
return list(obj)
raise TypeError(repr(obj) + " is not JSON serializable")

rj.dumps([set()], default=default_iterable)

Expand All @@ -107,11 +138,27 @@ def default_iterable(obj):


@pytest.mark.unit
def test_constants():
def test_serialize_sets_encoder():
class SetsEncoder(rj.Encoder):
def default(self, obj):
if isinstance(obj, set):
return list(obj)
raise TypeError(repr(obj) + " is not JSON serializable")

dumps = SetsEncoder()
dumps([set()])

with pytest.raises(TypeError):
rj.Encoder()([set()])


@pytest.mark.unit
@pytest.mark.parametrize('dumps,loads', ((rj.dumps, rj.loads), (rj.Encoder(), rj.Decoder())))
def test_constants(dumps, loads):
for c in [None, True, False]:
assert rj.loads(rj.dumps(c)) is c
assert rj.loads(rj.dumps([c]))[0] is c
assert rj.loads(rj.dumps({'a': c}))['a'] is c
assert loads(dumps(c)) is c
assert loads(dumps([c]))[0] is c
assert loads(dumps({'a': c}))['a'] is c


# TODO: Figure out what we want to do here
Expand Down
15 changes: 9 additions & 6 deletions tests/test_circular.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,31 @@


@pytest.mark.unit
def test_circular_dict():
@pytest.mark.parametrize('dumps', (rj.dumps, rj.Encoder()))
def test_circular_dict(dumps):
dct = {}
dct['a'] = dct

with pytest.raises(OverflowError):
rj.dumps(dct)
dumps(dct)


@pytest.mark.unit
def test_circular_list():
@pytest.mark.parametrize('dumps', (rj.dumps, rj.Encoder()))
def test_circular_list(dumps):
lst = []
lst.append(lst)

with pytest.raises(OverflowError):
rj.dumps(lst)
dumps(lst)


@pytest.mark.unit
def test_circular_composite():
@pytest.mark.parametrize('dumps', (rj.dumps, rj.Encoder()))
def test_circular_composite(dumps):
dct2 = {}
dct2['a'] = []
dct2['a'].append(dct2)

with pytest.raises(OverflowError):
rj.dumps(dct2)
dumps(dct2)
74 changes: 71 additions & 3 deletions tests/test_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


@pytest.mark.unit
def test_infinity():
def test_infinity_f():
inf = float("inf")

dumped = rj.dumps(inf)
Expand Down Expand Up @@ -37,7 +37,30 @@ def test_infinity():


@pytest.mark.unit
def test_negative_infinity():
def test_infinity_c():
inf = float("inf")

dumped = rj.Encoder()(inf)
loaded = rj.Decoder()(dumped)
assert loaded == inf

with pytest.raises(ValueError):
rj.Encoder(number_mode=None)(inf)

d = Decimal(inf)
assert d.is_infinite()

with pytest.raises(ValueError):
rj.Encoder(number_mode=rj.NM_DECIMAL)(d)

dumped = rj.Encoder(number_mode=rj.NM_DECIMAL|rj.NM_NAN)(d)
loaded = rj.Decoder(number_mode=rj.NM_DECIMAL|rj.NM_NAN)(dumped)
assert loaded == inf
assert loaded.is_infinite()


@pytest.mark.unit
def test_negative_infinity_f():
inf = float("-infinity")
dumped = rj.dumps(inf)
loaded = rj.loads(dumped)
Expand Down Expand Up @@ -66,7 +89,29 @@ def test_negative_infinity():


@pytest.mark.unit
def test_nan():
def test_negative_infinity_c():
inf = float("-infinity")
dumped = rj.Encoder()(inf)
loaded = rj.Decoder()(dumped)
assert loaded == inf

with pytest.raises(ValueError):
rj.Encoder(number_mode=None)(inf)

d = Decimal(inf)
assert d.is_infinite()

with pytest.raises(ValueError):
rj.Encoder(number_mode=rj.NM_DECIMAL)(d)

dumped = rj.Encoder(number_mode=rj.NM_DECIMAL|rj.NM_NAN)(d)
loaded = rj.Decoder(number_mode=rj.NM_DECIMAL|rj.NM_NAN)(dumped)
assert loaded == inf
assert loaded.is_infinite()


@pytest.mark.unit
def test_nan_f():
nan = float("nan")
dumped = rj.dumps(nan)
loaded = rj.loads(dumped)
Expand All @@ -89,3 +134,26 @@ def test_nan():
dumped = rj.dumps(d, number_mode=rj.NM_DECIMAL|rj.NM_NAN)
loaded = rj.loads(dumped, number_mode=rj.NM_DECIMAL|rj.NM_NAN)
assert loaded.is_nan()


@pytest.mark.unit
def test_nan_c():
nan = float("nan")
dumped = rj.Encoder()(nan)
loaded = rj.Decoder()(dumped)

assert math.isnan(nan)
assert math.isnan(loaded)

with pytest.raises(ValueError):
rj.Encoder(number_mode=None)(nan)

d = Decimal(nan)
assert d.is_nan()

with pytest.raises(ValueError):
rj.Encoder(number_mode=rj.NM_DECIMAL)(d)

dumped = rj.Encoder(number_mode=rj.NM_DECIMAL|rj.NM_NAN)(d)
loaded = rj.Decoder(number_mode=rj.NM_DECIMAL|rj.NM_NAN)(dumped)
assert loaded.is_nan()
51 changes: 48 additions & 3 deletions tests/test_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,34 @@ def test_skipkeys():


@pytest.mark.unit
def test_ensure_ascii():
def test_skip_invalid_keys():
o = {True: False, -1: 1, 1.1: 1.1, (1,2): "foo", b"asdf": 1, None: None}

with pytest.raises(TypeError):
rj.Encoder()(o)

with pytest.raises(TypeError):
rj.Encoder(skip_invalid_keys=False)(o)

assert rj.Encoder(skip_invalid_keys=True)(o) == '{}'


@pytest.mark.unit
def test_ensure_ascii_f():
s = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
assert rj.dumps(s) == '"\\u03B1\\u03A9"'
assert rj.dumps(s, ensure_ascii=True) == '"\\u03B1\\u03A9"'
assert rj.dumps(s, ensure_ascii=False) == '"%s"' % s


@pytest.mark.unit
def test_ensure_ascii_c():
s = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
assert rj.Encoder()(s) == '"\\u03B1\\u03A9"'
assert rj.Encoder(ensure_ascii=True)(s) == '"\\u03B1\\u03A9"'
assert rj.Encoder(ensure_ascii=False)(s) == '"%s"' % s


@pytest.mark.unit
def test_allow_nan():
f = [1.1, float("inf"), 2.2, float("nan"), 3.3, float("-inf"), 4.4]
Expand Down Expand Up @@ -70,12 +91,11 @@ def test_allow_nan():


@pytest.mark.unit
def test_native():
def test_native_f():
f = [-1, 1, 1.1, -2.2]
expected = '[-1,1,1.1,-2.2]'
assert rj.dumps(f, number_mode=rj.NM_NATIVE) == expected
assert rj.dumps(f) == expected
assert rj.loads(expected) == f
assert rj.loads(expected, number_mode=rj.NM_NATIVE) == f
assert rj.loads(expected) == f

Expand All @@ -94,6 +114,31 @@ def test_native():
parse_mode=rj.PM_COMMENTS | rj.PM_TRAILING_COMMAS) == expected


@pytest.mark.unit
def test_native_c():
f = [-1, 1, 1.1, -2.2]
expected = '[-1,1,1.1,-2.2]'
assert rj.Encoder(number_mode=rj.NM_NATIVE)(f) == expected
assert rj.Encoder()(f) == expected
assert rj.Decoder(number_mode=rj.NM_NATIVE)(expected) == f
assert rj.Decoder()(expected) == f

trailing_comma = '[-1,1,1.1,-2.2,]'
pytest.raises(ValueError, rj.Decoder(number_mode=rj.NM_NATIVE), trailing_comma)
expected = [-1,1,1.1,-2.2]
assert rj.Decoder(number_mode=rj.NM_NATIVE,
parse_mode=rj.PM_TRAILING_COMMAS)(trailing_comma) == expected

comments = '[-1,1,/*1.1,*/-2.2,]'
pytest.raises(ValueError, rj.Decoder(number_mode=rj.NM_NATIVE), comments)
pytest.raises(ValueError, rj.Decoder(number_mode=rj.NM_NATIVE,
parse_mode=rj.PM_TRAILING_COMMAS),
comments)
expected = [-1,1,-2.2]
assert rj.Decoder(number_mode=rj.NM_NATIVE,
parse_mode=rj.PM_COMMENTS | rj.PM_TRAILING_COMMAS)(comments) == expected


@pytest.mark.unit
def test_parse_mode():
trailing_comma = '[-1,1,1.1,-2.2,]'
Expand Down

0 comments on commit 9e34c01

Please sign in to comment.