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