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