xref: /aosp_15_r20/external/yapf/yapftests/main_test.py (revision 7249d1a64f4850ccf838e62a46276f891f72998e)
1*7249d1a6SKrzysztof Kosiński# -*- coding: utf-8 -*-
2*7249d1a6SKrzysztof Kosiński# Copyright 2015 Google Inc. All Rights Reserved.
3*7249d1a6SKrzysztof Kosiński#
4*7249d1a6SKrzysztof Kosiński# Licensed under the Apache License, Version 2.0 (the "License");
5*7249d1a6SKrzysztof Kosiński# you may not use this file except in compliance with the License.
6*7249d1a6SKrzysztof Kosiński# You may obtain a copy of the License at
7*7249d1a6SKrzysztof Kosiński#
8*7249d1a6SKrzysztof Kosiński#     http://www.apache.org/licenses/LICENSE-2.0
9*7249d1a6SKrzysztof Kosiński#
10*7249d1a6SKrzysztof Kosiński# Unless required by applicable law or agreed to in writing, software
11*7249d1a6SKrzysztof Kosiński# distributed under the License is distributed on an "AS IS" BASIS,
12*7249d1a6SKrzysztof Kosiński# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*7249d1a6SKrzysztof Kosiński# See the License for the specific language governing permissions and
14*7249d1a6SKrzysztof Kosiński# limitations under the License.
15*7249d1a6SKrzysztof Kosiński"""Tests for yapf.__init__.main."""
16*7249d1a6SKrzysztof Kosiński
17*7249d1a6SKrzysztof Kosińskifrom contextlib import contextmanager
18*7249d1a6SKrzysztof Kosińskiimport sys
19*7249d1a6SKrzysztof Kosińskiimport unittest
20*7249d1a6SKrzysztof Kosińskiimport yapf
21*7249d1a6SKrzysztof Kosiński
22*7249d1a6SKrzysztof Kosińskifrom yapf.yapflib import py3compat
23*7249d1a6SKrzysztof Kosiński
24*7249d1a6SKrzysztof Kosińskifrom yapftests import yapf_test_helper
25*7249d1a6SKrzysztof Kosiński
26*7249d1a6SKrzysztof Kosiński
27*7249d1a6SKrzysztof Kosińskiclass IO(object):
28*7249d1a6SKrzysztof Kosiński  """IO is a thin wrapper around StringIO.
29*7249d1a6SKrzysztof Kosiński
30*7249d1a6SKrzysztof Kosiński  This is strictly to wrap the Python 3 StringIO object so that it can supply a
31*7249d1a6SKrzysztof Kosiński  "buffer" attribute.
32*7249d1a6SKrzysztof Kosiński  """
33*7249d1a6SKrzysztof Kosiński
34*7249d1a6SKrzysztof Kosiński  class Buffer(object):
35*7249d1a6SKrzysztof Kosiński
36*7249d1a6SKrzysztof Kosiński    def __init__(self):
37*7249d1a6SKrzysztof Kosiński      self.string_io = py3compat.StringIO()
38*7249d1a6SKrzysztof Kosiński
39*7249d1a6SKrzysztof Kosiński    def write(self, s):
40*7249d1a6SKrzysztof Kosiński      if py3compat.PY3 and isinstance(s, bytes):
41*7249d1a6SKrzysztof Kosiński        s = str(s, 'utf-8')
42*7249d1a6SKrzysztof Kosiński      self.string_io.write(s)
43*7249d1a6SKrzysztof Kosiński
44*7249d1a6SKrzysztof Kosiński    def getvalue(self):
45*7249d1a6SKrzysztof Kosiński      return self.string_io.getvalue()
46*7249d1a6SKrzysztof Kosiński
47*7249d1a6SKrzysztof Kosiński  def __init__(self):
48*7249d1a6SKrzysztof Kosiński    self.buffer = self.Buffer()
49*7249d1a6SKrzysztof Kosiński
50*7249d1a6SKrzysztof Kosiński  def write(self, s):
51*7249d1a6SKrzysztof Kosiński    self.buffer.write(s)
52*7249d1a6SKrzysztof Kosiński
53*7249d1a6SKrzysztof Kosiński  def getvalue(self):
54*7249d1a6SKrzysztof Kosiński    return self.buffer.getvalue()
55*7249d1a6SKrzysztof Kosiński
56*7249d1a6SKrzysztof Kosiński
57*7249d1a6SKrzysztof Kosiński@contextmanager
58*7249d1a6SKrzysztof Kosińskidef captured_output():
59*7249d1a6SKrzysztof Kosiński  new_out, new_err = IO(), IO()
60*7249d1a6SKrzysztof Kosiński  old_out, old_err = sys.stdout, sys.stderr
61*7249d1a6SKrzysztof Kosiński  try:
62*7249d1a6SKrzysztof Kosiński    sys.stdout, sys.stderr = new_out, new_err
63*7249d1a6SKrzysztof Kosiński    yield sys.stdout, sys.stderr
64*7249d1a6SKrzysztof Kosiński  finally:
65*7249d1a6SKrzysztof Kosiński    sys.stdout, sys.stderr = old_out, old_err
66*7249d1a6SKrzysztof Kosiński
67*7249d1a6SKrzysztof Kosiński
68*7249d1a6SKrzysztof Kosiński@contextmanager
69*7249d1a6SKrzysztof Kosińskidef patched_input(code):
70*7249d1a6SKrzysztof Kosiński  """Monkey patch code as though it were coming from stdin."""
71*7249d1a6SKrzysztof Kosiński
72*7249d1a6SKrzysztof Kosiński  def lines():
73*7249d1a6SKrzysztof Kosiński    for line in code.splitlines():
74*7249d1a6SKrzysztof Kosiński      yield line
75*7249d1a6SKrzysztof Kosiński    raise EOFError()
76*7249d1a6SKrzysztof Kosiński
77*7249d1a6SKrzysztof Kosiński  def patch_raw_input(lines=lines()):
78*7249d1a6SKrzysztof Kosiński    return next(lines)
79*7249d1a6SKrzysztof Kosiński
80*7249d1a6SKrzysztof Kosiński  try:
81*7249d1a6SKrzysztof Kosiński    orig_raw_import = yapf.py3compat.raw_input
82*7249d1a6SKrzysztof Kosiński    yapf.py3compat.raw_input = patch_raw_input
83*7249d1a6SKrzysztof Kosiński    yield
84*7249d1a6SKrzysztof Kosiński  finally:
85*7249d1a6SKrzysztof Kosiński    yapf.py3compat.raw_input = orig_raw_import
86*7249d1a6SKrzysztof Kosiński
87*7249d1a6SKrzysztof Kosiński
88*7249d1a6SKrzysztof Kosińskiclass RunMainTest(yapf_test_helper.YAPFTest):
89*7249d1a6SKrzysztof Kosiński
90*7249d1a6SKrzysztof Kosiński  def testShouldHandleYapfError(self):
91*7249d1a6SKrzysztof Kosiński    """run_main should handle YapfError and sys.exit(1)."""
92*7249d1a6SKrzysztof Kosiński    expected_message = 'yapf: input filenames did not match any python files\n'
93*7249d1a6SKrzysztof Kosiński    sys.argv = ['yapf', 'foo.c']
94*7249d1a6SKrzysztof Kosiński    with captured_output() as (out, err):
95*7249d1a6SKrzysztof Kosiński      with self.assertRaises(SystemExit):
96*7249d1a6SKrzysztof Kosiński        yapf.run_main()
97*7249d1a6SKrzysztof Kosiński      self.assertEqual(out.getvalue(), '')
98*7249d1a6SKrzysztof Kosiński      self.assertEqual(err.getvalue(), expected_message)
99*7249d1a6SKrzysztof Kosiński
100*7249d1a6SKrzysztof Kosiński
101*7249d1a6SKrzysztof Kosińskiclass MainTest(yapf_test_helper.YAPFTest):
102*7249d1a6SKrzysztof Kosiński
103*7249d1a6SKrzysztof Kosiński  def testNoPythonFilesMatched(self):
104*7249d1a6SKrzysztof Kosiński    with self.assertRaisesRegex(yapf.errors.YapfError,
105*7249d1a6SKrzysztof Kosiński                                'did not match any python files'):
106*7249d1a6SKrzysztof Kosiński      yapf.main(['yapf', 'foo.c'])
107*7249d1a6SKrzysztof Kosiński
108*7249d1a6SKrzysztof Kosiński  def testEchoInput(self):
109*7249d1a6SKrzysztof Kosiński    code = 'a = 1\nb = 2\n'
110*7249d1a6SKrzysztof Kosiński    with patched_input(code):
111*7249d1a6SKrzysztof Kosiński      with captured_output() as (out, _):
112*7249d1a6SKrzysztof Kosiński        ret = yapf.main([])
113*7249d1a6SKrzysztof Kosiński        self.assertEqual(ret, 0)
114*7249d1a6SKrzysztof Kosiński        self.assertEqual(out.getvalue(), code)
115*7249d1a6SKrzysztof Kosiński
116*7249d1a6SKrzysztof Kosiński  def testEchoInputWithStyle(self):
117*7249d1a6SKrzysztof Kosiński    code = 'def f(a = 1\n\n):\n    return 2*a\n'
118*7249d1a6SKrzysztof Kosiński    yapf_code = 'def f(a=1):\n  return 2 * a\n'
119*7249d1a6SKrzysztof Kosiński    with patched_input(code):
120*7249d1a6SKrzysztof Kosiński      with captured_output() as (out, _):
121*7249d1a6SKrzysztof Kosiński        ret = yapf.main(['-', '--style=yapf'])
122*7249d1a6SKrzysztof Kosiński        self.assertEqual(ret, 0)
123*7249d1a6SKrzysztof Kosiński        self.assertEqual(out.getvalue(), yapf_code)
124*7249d1a6SKrzysztof Kosiński
125*7249d1a6SKrzysztof Kosiński  def testEchoBadInput(self):
126*7249d1a6SKrzysztof Kosiński    bad_syntax = '  a = 1\n'
127*7249d1a6SKrzysztof Kosiński    with patched_input(bad_syntax):
128*7249d1a6SKrzysztof Kosiński      with captured_output() as (_, _):
129*7249d1a6SKrzysztof Kosiński        with self.assertRaisesRegex(yapf.errors.YapfError, 'unexpected indent'):
130*7249d1a6SKrzysztof Kosiński          yapf.main([])
131*7249d1a6SKrzysztof Kosiński
132*7249d1a6SKrzysztof Kosiński  def testHelp(self):
133*7249d1a6SKrzysztof Kosiński    with captured_output() as (out, _):
134*7249d1a6SKrzysztof Kosiński      ret = yapf.main(['-', '--style-help', '--style=pep8'])
135*7249d1a6SKrzysztof Kosiński      self.assertEqual(ret, 0)
136*7249d1a6SKrzysztof Kosiński      help_message = out.getvalue()
137*7249d1a6SKrzysztof Kosiński      self.assertIn('indent_width=4', help_message)
138*7249d1a6SKrzysztof Kosiński      self.assertIn('The number of spaces required before a trailing comment.',
139*7249d1a6SKrzysztof Kosiński                    help_message)
140