1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
|
# -*- encoding: utf-8 -*-
from pypy.module._pypyjson.interp_decoder import JSONDecoder
def test_skip_whitespace():
s = ' hello '
dec = JSONDecoder('fake space', s)
assert dec.pos == 0
assert dec.skip_whitespace(0) == 3
assert dec.skip_whitespace(3) == 3
assert dec.skip_whitespace(8) == len(s)
dec.close()
def test_decode_key():
s1 = "123" * 100
s = ' "%s" "%s" ' % (s1, s1)
dec = JSONDecoder('fake space', s)
assert dec.pos == 0
x = dec.decode_key(0)
assert x == s1
# check caching
y = dec.decode_key(dec.pos)
assert y == s1
assert y is x
dec.close()
class AppTest(object):
spaceconfig = {"usemodules": ['_pypyjson']}
def test_raise_on_bytes(self):
import _pypyjson
raises(TypeError, _pypyjson.loads, b"42")
def test_decode_constants(self):
import _pypyjson
assert _pypyjson.loads('null') is None
raises(ValueError, _pypyjson.loads, 'nul')
raises(ValueError, _pypyjson.loads, 'nu')
raises(ValueError, _pypyjson.loads, 'n')
raises(ValueError, _pypyjson.loads, 'nuXX')
#
assert _pypyjson.loads('true') is True
raises(ValueError, _pypyjson.loads, 'tru')
raises(ValueError, _pypyjson.loads, 'tr')
raises(ValueError, _pypyjson.loads, 't')
raises(ValueError, _pypyjson.loads, 'trXX')
#
assert _pypyjson.loads('false') is False
raises(ValueError, _pypyjson.loads, 'fals')
raises(ValueError, _pypyjson.loads, 'fal')
raises(ValueError, _pypyjson.loads, 'fa')
raises(ValueError, _pypyjson.loads, 'f')
raises(ValueError, _pypyjson.loads, 'falXX')
def test_decode_string(self):
import _pypyjson
res = _pypyjson.loads('"hello"')
assert res == 'hello'
assert type(res) is str
def test_decode_string_utf8(self):
import _pypyjson
s = 'àèìòù'
raises(ValueError, _pypyjson.loads, '"%s"' % s.encode('utf-8'))
def test_skip_whitespace(self):
import _pypyjson
s = ' "hello" '
assert _pypyjson.loads(s) == 'hello'
s = ' "hello" extra'
raises(ValueError, "_pypyjson.loads(s)")
def test_unterminated_string(self):
import _pypyjson
s = '"hello' # missing the trailing "
raises(ValueError, "_pypyjson.loads(s)")
def test_escape_sequence(self):
import _pypyjson
assert _pypyjson.loads(r'"\\"') == '\\'
assert _pypyjson.loads(r'"\""') == '"'
assert _pypyjson.loads(r'"\/"') == '/'
assert _pypyjson.loads(r'"\b"') == '\b'
assert _pypyjson.loads(r'"\f"') == '\f'
assert _pypyjson.loads(r'"\n"') == '\n'
assert _pypyjson.loads(r'"\r"') == '\r'
assert _pypyjson.loads(r'"\t"') == '\t'
def test_escape_sequence_in_the_middle(self):
import _pypyjson
s = r'"hello\nworld"'
assert _pypyjson.loads(s) == "hello\nworld"
def test_unterminated_string_after_escape_sequence(self):
import _pypyjson
s = r'"hello\nworld' # missing the trailing "
raises(ValueError, "_pypyjson.loads(s)")
def test_escape_sequence_unicode(self):
import _pypyjson
s = r'"\u1234"'
assert _pypyjson.loads(s) == '\u1234'
def test_invalid_utf_8(self):
import _pypyjson
s = '"\xe0"' # this is an invalid UTF8 sequence inside a string
assert _pypyjson.loads(s) == 'à'
def test_decode_numeric(self):
import sys
import _pypyjson
def check(s, val):
res = _pypyjson.loads(s)
assert type(res) is type(val)
assert res == val
#
check('42', 42)
check('-42', -42)
check('42.123', 42.123)
check('42E0', 42.0)
check('42E3', 42000.0)
check('42E-1', 4.2)
check('42E+1', 420.0)
check('42.123E3', 42123.0)
check('0', 0)
check('-0', 0)
check('0.123', 0.123)
check('0E3', 0.0)
check('5E0001', 50.0)
check(str(1 << 32), 1 << 32)
check(str(1 << 64), 1 << 64)
#
x = str(sys.maxsize+1) + '.123'
check(x, float(x))
x = str(sys.maxsize+1) + 'E1'
check(x, float(x))
x = str(sys.maxsize+1) + 'E-1'
check(x, float(x))
#
check('1E400', float('inf'))
## # these are non-standard but supported by CPython json
check('Infinity', float('inf'))
check('-Infinity', float('-inf'))
def test_nan(self):
import math
import _pypyjson
res = _pypyjson.loads('NaN')
assert math.isnan(res)
def test_decode_numeric_invalid(self):
import _pypyjson
def error(s):
raises(ValueError, _pypyjson.loads, s)
#
error(' 42 abc')
error('.123')
error('+123')
error('12.')
error('12.-3')
error('12E')
error('12E-')
error('0123') # numbers can't start with 0
def test_decode_object(self):
import _pypyjson
assert _pypyjson.loads('{}') == {}
assert _pypyjson.loads('{ }') == {}
#
s = '{"hello": "world", "aaa": "bbb"}'
assert _pypyjson.loads(s) == {'hello': 'world',
'aaa': 'bbb'}
raises(ValueError, _pypyjson.loads, '{"key"')
raises(ValueError, _pypyjson.loads, '{"key": 42')
def test_decode_object_nonstring_key(self):
import _pypyjson
raises(ValueError, "_pypyjson.loads('{42: 43}')")
def test_decode_array(self):
import _pypyjson
assert _pypyjson.loads('[]') == []
assert _pypyjson.loads('[ ]') == []
assert _pypyjson.loads('[1]') == [1]
assert _pypyjson.loads('[1, 2]') == [1, 2]
raises(ValueError, "_pypyjson.loads('[1: 2]')")
raises(ValueError, "_pypyjson.loads('[1, 2')")
raises(ValueError, """_pypyjson.loads('["extra comma",]')""")
def test_unicode_surrogate_pair(self):
import _pypyjson
expected = 'z\U0001d120x'
res = _pypyjson.loads('"z\\ud834\\udd20x"')
assert res == expected
def test_lone_surrogate(self):
import _pypyjson
json = '{"a":"\\uD83D"}'
res = _pypyjson.loads(json)
assert res == {u'a': u'\ud83d'}
def test_cache_keys(self):
import _pypyjson
json = '[{"a": 1}, {"a": 2}]'
res = _pypyjson.loads(json)
assert res == [{u'a': 1}, {u'a': 2}]
def test_tab_in_string_should_fail(self):
import _pypyjson
# http://json.org/JSON_checker/test/fail25.json
s = '["\ttab\tcharacter\tin\tstring\t"]'
raises(ValueError, "_pypyjson.loads(s)")
def test_raw_encode_basestring_ascii(self):
import _pypyjson
def check(s):
s = _pypyjson.raw_encode_basestring_ascii(s)
assert type(s) is str
return s
assert check("") == ""
assert check(u"") == ""
assert check("abc ") == "abc "
assert check(u"abc ") == "abc "
assert check("\xc0") == "\\u00c0"
assert check("\xc2\x84") == "\\u00c2\\u0084"
assert check(u"\ud808\udf45") == "\\ud808\\udf45"
assert check(u"\U00012345") == "\\ud808\\udf45"
assert check("a\"c") == "a\\\"c"
assert check("\\\"\b\f\n\r\t") == '\\\\\\"\\b\\f\\n\\r\\t'
assert check("\x07") == "\\u0007"
def test_error_position(self):
import _pypyjson
test_cases = [
('[,', "Unexpected ',' at", 1),
('{"spam":[}', "Unexpected '}' at", 9),
('[42:', "Unexpected ':' when decoding array", 3),
('[42 "spam"', "Unexpected '\"' when decoding array", 4),
('[42,]', "Unexpected ']' at", 4),
('{"spam":[42}', "Unexpected '}' when decoding array", 11),
('["]', 'Unterminated string starting at', 1),
('["spam":', "Unexpected ':' when decoding array", 7),
('[{]', "Key name must be string at char", 2),
]
for inputtext, errmsg, errpos in test_cases:
exc = raises(ValueError, _pypyjson.loads, inputtext)
assert exc.value.args == (errmsg, inputtext, errpos)
def test_keys_reuse(self):
import _pypyjson
s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]'
rval = _pypyjson.loads(s)
(a, b), (c, d) = sorted(rval[0]), sorted(rval[1])
assert a is c
assert b is d
def test_custom_error_class(self):
import _pypyjson
class MyError(Exception):
pass
exc = raises(MyError, _pypyjson.loads, 'nul', MyError)
assert exc.value.args == ('Error when decoding null at', 'nul', 1)
|