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