File: test__pypyjson.py

package info (click to toggle)
pypy3 7.0.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 111,848 kB
  • sloc: python: 1,291,746; ansic: 74,281; asm: 5,187; cpp: 3,017; sh: 2,533; makefile: 544; xml: 243; lisp: 45; csh: 21; awk: 4
file content (263 lines) | stat: -rw-r--r-- 8,854 bytes parent folder | download
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)