1 import errno
2 import os
3 import sys
4 import textwrap
5 import unittest
6 import subprocess
7
8 from test import support
9 from test.support import os_helper
10 from test.support.script_helper import assert_python_ok
11
12
13 @support.requires_subprocess()
14 class ESC[4;38;5;81mTestTool(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
15 data = """
16
17 [["blorpie"],[ "whoops" ] , [
18 ],\t"d-shtaeou",\r"d-nthiouh",
19 "i-vhbjkhnth", {"nifty":87}, {"morefield" :\tfalse,"field"
20 :"yes"} ]
21 """
22
23 expect_without_sort_keys = textwrap.dedent("""\
24 [
25 [
26 "blorpie"
27 ],
28 [
29 "whoops"
30 ],
31 [],
32 "d-shtaeou",
33 "d-nthiouh",
34 "i-vhbjkhnth",
35 {
36 "nifty": 87
37 },
38 {
39 "field": "yes",
40 "morefield": false
41 }
42 ]
43 """)
44
45 expect = textwrap.dedent("""\
46 [
47 [
48 "blorpie"
49 ],
50 [
51 "whoops"
52 ],
53 [],
54 "d-shtaeou",
55 "d-nthiouh",
56 "i-vhbjkhnth",
57 {
58 "nifty": 87
59 },
60 {
61 "morefield": false,
62 "field": "yes"
63 }
64 ]
65 """)
66
67 jsonlines_raw = textwrap.dedent("""\
68 {"ingredients":["frog", "water", "chocolate", "glucose"]}
69 {"ingredients":["chocolate","steel bolts"]}
70 """)
71
72 jsonlines_expect = textwrap.dedent("""\
73 {
74 "ingredients": [
75 "frog",
76 "water",
77 "chocolate",
78 "glucose"
79 ]
80 }
81 {
82 "ingredients": [
83 "chocolate",
84 "steel bolts"
85 ]
86 }
87 """)
88
89 def test_stdin_stdout(self):
90 args = sys.executable, '-m', 'json.tool'
91 process = subprocess.run(args, input=self.data, capture_output=True, text=True, check=True)
92 self.assertEqual(process.stdout, self.expect)
93 self.assertEqual(process.stderr, '')
94
95 def _create_infile(self, data=None):
96 infile = os_helper.TESTFN
97 with open(infile, "w", encoding="utf-8") as fp:
98 self.addCleanup(os.remove, infile)
99 fp.write(data or self.data)
100 return infile
101
102 def test_infile_stdout(self):
103 infile = self._create_infile()
104 rc, out, err = assert_python_ok('-m', 'json.tool', infile)
105 self.assertEqual(rc, 0)
106 self.assertEqual(out.splitlines(), self.expect.encode().splitlines())
107 self.assertEqual(err, b'')
108
109 def test_non_ascii_infile(self):
110 data = '{"msg": "\u3053\u3093\u306b\u3061\u306f"}'
111 expect = textwrap.dedent('''\
112 {
113 "msg": "\\u3053\\u3093\\u306b\\u3061\\u306f"
114 }
115 ''').encode()
116
117 infile = self._create_infile(data)
118 rc, out, err = assert_python_ok('-m', 'json.tool', infile)
119
120 self.assertEqual(rc, 0)
121 self.assertEqual(out.splitlines(), expect.splitlines())
122 self.assertEqual(err, b'')
123
124 def test_infile_outfile(self):
125 infile = self._create_infile()
126 outfile = os_helper.TESTFN + '.out'
127 rc, out, err = assert_python_ok('-m', 'json.tool', infile, outfile)
128 self.addCleanup(os.remove, outfile)
129 with open(outfile, "r", encoding="utf-8") as fp:
130 self.assertEqual(fp.read(), self.expect)
131 self.assertEqual(rc, 0)
132 self.assertEqual(out, b'')
133 self.assertEqual(err, b'')
134
135 def test_writing_in_place(self):
136 infile = self._create_infile()
137 rc, out, err = assert_python_ok('-m', 'json.tool', infile, infile)
138 with open(infile, "r", encoding="utf-8") as fp:
139 self.assertEqual(fp.read(), self.expect)
140 self.assertEqual(rc, 0)
141 self.assertEqual(out, b'')
142 self.assertEqual(err, b'')
143
144 def test_jsonlines(self):
145 args = sys.executable, '-m', 'json.tool', '--json-lines'
146 process = subprocess.run(args, input=self.jsonlines_raw, capture_output=True, text=True, check=True)
147 self.assertEqual(process.stdout, self.jsonlines_expect)
148 self.assertEqual(process.stderr, '')
149
150 def test_help_flag(self):
151 rc, out, err = assert_python_ok('-m', 'json.tool', '-h')
152 self.assertEqual(rc, 0)
153 self.assertTrue(out.startswith(b'usage: '))
154 self.assertEqual(err, b'')
155
156 def test_sort_keys_flag(self):
157 infile = self._create_infile()
158 rc, out, err = assert_python_ok('-m', 'json.tool', '--sort-keys', infile)
159 self.assertEqual(rc, 0)
160 self.assertEqual(out.splitlines(),
161 self.expect_without_sort_keys.encode().splitlines())
162 self.assertEqual(err, b'')
163
164 def test_indent(self):
165 input_ = '[1, 2]'
166 expect = textwrap.dedent('''\
167 [
168 1,
169 2
170 ]
171 ''')
172 args = sys.executable, '-m', 'json.tool', '--indent', '2'
173 process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
174 self.assertEqual(process.stdout, expect)
175 self.assertEqual(process.stderr, '')
176
177 def test_no_indent(self):
178 input_ = '[1,\n2]'
179 expect = '[1, 2]\n'
180 args = sys.executable, '-m', 'json.tool', '--no-indent'
181 process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
182 self.assertEqual(process.stdout, expect)
183 self.assertEqual(process.stderr, '')
184
185 def test_tab(self):
186 input_ = '[1, 2]'
187 expect = '[\n\t1,\n\t2\n]\n'
188 args = sys.executable, '-m', 'json.tool', '--tab'
189 process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
190 self.assertEqual(process.stdout, expect)
191 self.assertEqual(process.stderr, '')
192
193 def test_compact(self):
194 input_ = '[ 1 ,\n 2]'
195 expect = '[1,2]\n'
196 args = sys.executable, '-m', 'json.tool', '--compact'
197 process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
198 self.assertEqual(process.stdout, expect)
199 self.assertEqual(process.stderr, '')
200
201 def test_no_ensure_ascii_flag(self):
202 infile = self._create_infile('{"key":"💩"}')
203 outfile = os_helper.TESTFN + '.out'
204 self.addCleanup(os.remove, outfile)
205 assert_python_ok('-m', 'json.tool', '--no-ensure-ascii', infile, outfile)
206 with open(outfile, "rb") as f:
207 lines = f.read().splitlines()
208 # asserting utf-8 encoded output file
209 expected = [b'{', b' "key": "\xf0\x9f\x92\xa9"', b"}"]
210 self.assertEqual(lines, expected)
211
212 def test_ensure_ascii_default(self):
213 infile = self._create_infile('{"key":"💩"}')
214 outfile = os_helper.TESTFN + '.out'
215 self.addCleanup(os.remove, outfile)
216 assert_python_ok('-m', 'json.tool', infile, outfile)
217 with open(outfile, "rb") as f:
218 lines = f.read().splitlines()
219 # asserting an ascii encoded output file
220 expected = [b'{', rb' "key": "\ud83d\udca9"', b"}"]
221 self.assertEqual(lines, expected)
222
223 @unittest.skipIf(sys.platform =="win32", "The test is failed with ValueError on Windows")
224 def test_broken_pipe_error(self):
225 cmd = [sys.executable, '-m', 'json.tool']
226 proc = subprocess.Popen(cmd,
227 stdout=subprocess.PIPE,
228 stdin=subprocess.PIPE)
229 # bpo-39828: Closing before json.tool attempts to write into stdout.
230 proc.stdout.close()
231 proc.communicate(b'"{}"')
232 self.assertEqual(proc.returncode, errno.EPIPE)