Home | History | Annotate | Download | only in yapftests
      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 
     17 from contextlib import contextmanager
     18 import sys
     19 import unittest
     20 import yapf
     21 
     22 from yapf.yapflib import py3compat
     23 
     24 
     25 class IO(object):
     26   """IO is a thin wrapper around StringIO.
     27 
     28   This is strictly to wrap the Python 3 StringIO object so that it can supply a
     29   "buffer" attribute.
     30   """
     31 
     32   class Buffer(object):
     33 
     34     def __init__(self):
     35       self.string_io = py3compat.StringIO()
     36 
     37     def write(self, s):
     38       if py3compat.PY3 and isinstance(s, bytes):
     39         s = str(s, 'utf-8')
     40       self.string_io.write(s)
     41 
     42     def getvalue(self):
     43       return self.string_io.getvalue()
     44 
     45   def __init__(self):
     46     self.buffer = self.Buffer()
     47 
     48   def write(self, s):
     49     self.buffer.write(s)
     50 
     51   def getvalue(self):
     52     return self.buffer.getvalue()
     53 
     54 
     55 @contextmanager
     56 def captured_output():
     57   new_out, new_err = IO(), IO()
     58   old_out, old_err = sys.stdout, sys.stderr
     59   try:
     60     sys.stdout, sys.stderr = new_out, new_err
     61     yield sys.stdout, sys.stderr
     62   finally:
     63     sys.stdout, sys.stderr = old_out, old_err
     64 
     65 
     66 @contextmanager
     67 def patched_input(code):
     68   """Monkey patch code as though it were coming from stdin."""
     69 
     70   def lines():
     71     for line in code.splitlines():
     72       yield line
     73     raise EOFError()
     74 
     75   def patch_raw_input(lines=lines()):
     76     return next(lines)
     77 
     78   try:
     79     orig_raw_import = yapf.py3compat.raw_input
     80     yapf.py3compat.raw_input = patch_raw_input
     81     yield
     82   finally:
     83     yapf.py3compat.raw_input = orig_raw_import
     84 
     85 
     86 class RunMainTest(unittest.TestCase):
     87 
     88   def testShouldHandleYapfError(self):
     89     """run_main should handle YapfError and sys.exit(1)."""
     90     expected_message = 'yapf: Input filenames did not match any python files\n'
     91     sys.argv = ['yapf', 'foo.c']
     92     with captured_output() as (out, err):
     93       with self.assertRaises(SystemExit):
     94         yapf.run_main()
     95       self.assertEqual(out.getvalue(), '')
     96       self.assertEqual(err.getvalue(), expected_message)
     97 
     98 
     99 class MainTest(unittest.TestCase):
    100 
    101   def testNoPythonFilesMatched(self):
    102     with self.assertRaisesRegexp(yapf.errors.YapfError,
    103                                  'did not match any python files'):
    104       yapf.main(['yapf', 'foo.c'])
    105 
    106   def testEchoInput(self):
    107     code = 'a = 1\nb = 2\n'
    108     with patched_input(code):
    109       with captured_output() as (out, _):
    110         ret = yapf.main([])
    111         self.assertEqual(ret, 0)
    112         self.assertEqual(out.getvalue(), code)
    113 
    114   def testEchoInputWithStyle(self):
    115     code = 'def f(a = 1):\n    return 2*a\n'
    116     chromium_code = 'def f(a=1):\n  return 2 * a\n'
    117     with patched_input(code):
    118       with captured_output() as (out, _):
    119         ret = yapf.main(['-', '--style=chromium'])
    120         self.assertEqual(ret, 0)
    121         self.assertEqual(out.getvalue(), chromium_code)
    122 
    123   def testEchoBadInput(self):
    124     bad_syntax = '  a = 1\n'
    125     with patched_input(bad_syntax):
    126       with captured_output() as (_, _):
    127         with self.assertRaisesRegexp(SyntaxError, 'unexpected indent'):
    128           yapf.main([])
    129 
    130   def testHelp(self):
    131     with captured_output() as (out, _):
    132       ret = yapf.main(['-', '--style-help', '--style=pep8'])
    133       self.assertEqual(ret, 0)
    134       help_message = out.getvalue()
    135       self.assertIn('indent_width=4', help_message)
    136       self.assertIn('The number of spaces required before a trailing comment.',
    137                     help_message)
    138 
    139   def testVersion(self):
    140     with captured_output() as (out, _):
    141       ret = yapf.main(['-', '--version'])
    142       self.assertEqual(ret, 0)
    143       version = 'yapf {}\n'.format(yapf.__version__)
    144       self.assertEqual(version, out.getvalue())
    145