1 from test.test_json import PyTest, CTest
2
3 # 2007-10-05
4 JSONDOCS = [
5 # https://json.org/JSON_checker/test/fail1.json
6 '"A JSON payload should be an object or array, not a string."',
7 # https://json.org/JSON_checker/test/fail2.json
8 '["Unclosed array"',
9 # https://json.org/JSON_checker/test/fail3.json
10 '{unquoted_key: "keys must be quoted"}',
11 # https://json.org/JSON_checker/test/fail4.json
12 '["extra comma",]',
13 # https://json.org/JSON_checker/test/fail5.json
14 '["double extra comma",,]',
15 # https://json.org/JSON_checker/test/fail6.json
16 '[ , "<-- missing value"]',
17 # https://json.org/JSON_checker/test/fail7.json
18 '["Comma after the close"],',
19 # https://json.org/JSON_checker/test/fail8.json
20 '["Extra close"]]',
21 # https://json.org/JSON_checker/test/fail9.json
22 '{"Extra comma": true,}',
23 # https://json.org/JSON_checker/test/fail10.json
24 '{"Extra value after close": true} "misplaced quoted value"',
25 # https://json.org/JSON_checker/test/fail11.json
26 '{"Illegal expression": 1 + 2}',
27 # https://json.org/JSON_checker/test/fail12.json
28 '{"Illegal invocation": alert()}',
29 # https://json.org/JSON_checker/test/fail13.json
30 '{"Numbers cannot have leading zeroes": 013}',
31 # https://json.org/JSON_checker/test/fail14.json
32 '{"Numbers cannot be hex": 0x14}',
33 # https://json.org/JSON_checker/test/fail15.json
34 '["Illegal backslash escape: \\x15"]',
35 # https://json.org/JSON_checker/test/fail16.json
36 '[\\naked]',
37 # https://json.org/JSON_checker/test/fail17.json
38 '["Illegal backslash escape: \\017"]',
39 # https://json.org/JSON_checker/test/fail18.json
40 '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]',
41 # https://json.org/JSON_checker/test/fail19.json
42 '{"Missing colon" null}',
43 # https://json.org/JSON_checker/test/fail20.json
44 '{"Double colon":: null}',
45 # https://json.org/JSON_checker/test/fail21.json
46 '{"Comma instead of colon", null}',
47 # https://json.org/JSON_checker/test/fail22.json
48 '["Colon instead of comma": false]',
49 # https://json.org/JSON_checker/test/fail23.json
50 '["Bad value", truth]',
51 # https://json.org/JSON_checker/test/fail24.json
52 "['single quote']",
53 # https://json.org/JSON_checker/test/fail25.json
54 '["\ttab\tcharacter\tin\tstring\t"]',
55 # https://json.org/JSON_checker/test/fail26.json
56 '["tab\\ character\\ in\\ string\\ "]',
57 # https://json.org/JSON_checker/test/fail27.json
58 '["line\nbreak"]',
59 # https://json.org/JSON_checker/test/fail28.json
60 '["line\\\nbreak"]',
61 # https://json.org/JSON_checker/test/fail29.json
62 '[0e]',
63 # https://json.org/JSON_checker/test/fail30.json
64 '[0e+]',
65 # https://json.org/JSON_checker/test/fail31.json
66 '[0e+-1]',
67 # https://json.org/JSON_checker/test/fail32.json
68 '{"Comma instead if closing brace": true,',
69 # https://json.org/JSON_checker/test/fail33.json
70 '["mismatch"}',
71 # https://code.google.com/archive/p/simplejson/issues/3
72 '["A\u001FZ control characters in string"]',
73 ]
74
75 SKIPS = {
76 1: "why not have a string payload?",
77 18: "spec doesn't specify any nesting limitations",
78 }
79
80 class ESC[4;38;5;81mTestFail:
81 def test_failures(self):
82 for idx, doc in enumerate(JSONDOCS):
83 idx = idx + 1
84 if idx in SKIPS:
85 self.loads(doc)
86 continue
87 try:
88 self.loads(doc)
89 except self.JSONDecodeError:
90 pass
91 else:
92 self.fail("Expected failure for fail{0}.json: {1!r}".format(idx, doc))
93
94 def test_non_string_keys_dict(self):
95 data = {'a' : 1, (1, 2) : 2}
96 with self.assertRaisesRegex(TypeError,
97 'keys must be str, int, float, bool or None, not tuple'):
98 self.dumps(data)
99
100 def test_not_serializable(self):
101 import sys
102 with self.assertRaisesRegex(TypeError,
103 'Object of type module is not JSON serializable'):
104 self.dumps(sys)
105
106 def test_truncated_input(self):
107 test_cases = [
108 ('', 'Expecting value', 0),
109 ('[', 'Expecting value', 1),
110 ('[42', "Expecting ',' delimiter", 3),
111 ('[42,', 'Expecting value', 4),
112 ('["', 'Unterminated string starting at', 1),
113 ('["spam', 'Unterminated string starting at', 1),
114 ('["spam"', "Expecting ',' delimiter", 7),
115 ('["spam",', 'Expecting value', 8),
116 ('{', 'Expecting property name enclosed in double quotes', 1),
117 ('{"', 'Unterminated string starting at', 1),
118 ('{"spam', 'Unterminated string starting at', 1),
119 ('{"spam"', "Expecting ':' delimiter", 7),
120 ('{"spam":', 'Expecting value', 8),
121 ('{"spam":42', "Expecting ',' delimiter", 10),
122 ('{"spam":42,', 'Expecting property name enclosed in double quotes', 11),
123 ]
124 test_cases += [
125 ('"', 'Unterminated string starting at', 0),
126 ('"spam', 'Unterminated string starting at', 0),
127 ]
128 for data, msg, idx in test_cases:
129 with self.assertRaises(self.JSONDecodeError) as cm:
130 self.loads(data)
131 err = cm.exception
132 self.assertEqual(err.msg, msg)
133 self.assertEqual(err.pos, idx)
134 self.assertEqual(err.lineno, 1)
135 self.assertEqual(err.colno, idx + 1)
136 self.assertEqual(str(err),
137 '%s: line 1 column %d (char %d)' %
138 (msg, idx + 1, idx))
139
140 def test_unexpected_data(self):
141 test_cases = [
142 ('[,', 'Expecting value', 1),
143 ('{"spam":[}', 'Expecting value', 9),
144 ('[42:', "Expecting ',' delimiter", 3),
145 ('[42 "spam"', "Expecting ',' delimiter", 4),
146 ('[42,]', 'Expecting value', 4),
147 ('{"spam":[42}', "Expecting ',' delimiter", 11),
148 ('["]', 'Unterminated string starting at', 1),
149 ('["spam":', "Expecting ',' delimiter", 7),
150 ('["spam",]', 'Expecting value', 8),
151 ('{:', 'Expecting property name enclosed in double quotes', 1),
152 ('{,', 'Expecting property name enclosed in double quotes', 1),
153 ('{42', 'Expecting property name enclosed in double quotes', 1),
154 ('[{]', 'Expecting property name enclosed in double quotes', 2),
155 ('{"spam",', "Expecting ':' delimiter", 7),
156 ('{"spam"}', "Expecting ':' delimiter", 7),
157 ('[{"spam"]', "Expecting ':' delimiter", 8),
158 ('{"spam":}', 'Expecting value', 8),
159 ('[{"spam":]', 'Expecting value', 9),
160 ('{"spam":42 "ham"', "Expecting ',' delimiter", 11),
161 ('[{"spam":42]', "Expecting ',' delimiter", 11),
162 ('{"spam":42,}', 'Expecting property name enclosed in double quotes', 11),
163 ]
164 for data, msg, idx in test_cases:
165 with self.assertRaises(self.JSONDecodeError) as cm:
166 self.loads(data)
167 err = cm.exception
168 self.assertEqual(err.msg, msg)
169 self.assertEqual(err.pos, idx)
170 self.assertEqual(err.lineno, 1)
171 self.assertEqual(err.colno, idx + 1)
172 self.assertEqual(str(err),
173 '%s: line 1 column %d (char %d)' %
174 (msg, idx + 1, idx))
175
176 def test_extra_data(self):
177 test_cases = [
178 ('[]]', 'Extra data', 2),
179 ('{}}', 'Extra data', 2),
180 ('[],[]', 'Extra data', 2),
181 ('{},{}', 'Extra data', 2),
182 ]
183 test_cases += [
184 ('42,"spam"', 'Extra data', 2),
185 ('"spam",42', 'Extra data', 6),
186 ]
187 for data, msg, idx in test_cases:
188 with self.assertRaises(self.JSONDecodeError) as cm:
189 self.loads(data)
190 err = cm.exception
191 self.assertEqual(err.msg, msg)
192 self.assertEqual(err.pos, idx)
193 self.assertEqual(err.lineno, 1)
194 self.assertEqual(err.colno, idx + 1)
195 self.assertEqual(str(err),
196 '%s: line 1 column %d (char %d)' %
197 (msg, idx + 1, idx))
198
199 def test_linecol(self):
200 test_cases = [
201 ('!', 1, 1, 0),
202 (' !', 1, 2, 1),
203 ('\n!', 2, 1, 1),
204 ('\n \n\n !', 4, 6, 10),
205 ]
206 for data, line, col, idx in test_cases:
207 with self.assertRaises(self.JSONDecodeError) as cm:
208 self.loads(data)
209 err = cm.exception
210 self.assertEqual(err.msg, 'Expecting value')
211 self.assertEqual(err.pos, idx)
212 self.assertEqual(err.lineno, line)
213 self.assertEqual(err.colno, col)
214 self.assertEqual(str(err),
215 'Expecting value: line %s column %d (char %d)' %
216 (line, col, idx))
217
218 class ESC[4;38;5;81mTestPyFail(ESC[4;38;5;149mTestFail, ESC[4;38;5;149mPyTest): pass
219 class ESC[4;38;5;81mTestCFail(ESC[4;38;5;149mTestFail, ESC[4;38;5;149mCTest): pass