Home | History | Annotate | Download | only in style
      1 # Copyright (C) 2010 Chris Jerdonek (cjerdonek (at] webkit.org)
      2 #
      3 # Redistribution and use in source and binary forms, with or without
      4 # modification, are permitted provided that the following conditions
      5 # are met:
      6 # 1.  Redistributions of source code must retain the above copyright
      7 #     notice, this list of conditions and the following disclaimer.
      8 # 2.  Redistributions in binary form must reproduce the above copyright
      9 #     notice, this list of conditions and the following disclaimer in the
     10 #     documentation and/or other materials provided with the distribution.
     11 #
     12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     13 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     14 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     15 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     16 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     17 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     18 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     19 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     20 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     21 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     22 
     23 """Unit tests for parser.py."""
     24 
     25 import unittest
     26 
     27 from webkitpy.common.system.logtesting import LoggingTestCase
     28 from webkitpy.style.optparser import ArgumentParser
     29 from webkitpy.style.optparser import ArgumentPrinter
     30 from webkitpy.style.optparser import CommandOptionValues as ProcessorOptions
     31 from webkitpy.style.optparser import DefaultCommandOptionValues
     32 
     33 
     34 class ArgumentPrinterTest(unittest.TestCase):
     35 
     36     """Tests the ArgumentPrinter class."""
     37 
     38     _printer = ArgumentPrinter()
     39 
     40     def _create_options(self,
     41                         output_format='emacs',
     42                         min_confidence=3,
     43                         filter_rules=[],
     44                         git_commit=None):
     45         return ProcessorOptions(filter_rules=filter_rules,
     46                                 git_commit=git_commit,
     47                                 min_confidence=min_confidence,
     48                                 output_format=output_format)
     49 
     50     def test_to_flag_string(self):
     51         options = self._create_options('vs7', 5, ['+foo', '-bar'], 'git')
     52         self.assertEquals('--filter=+foo,-bar --git-commit=git '
     53                           '--min-confidence=5 --output=vs7',
     54                           self._printer.to_flag_string(options))
     55 
     56         # This is to check that --filter and --git-commit do not
     57         # show up when not user-specified.
     58         options = self._create_options()
     59         self.assertEquals('--min-confidence=3 --output=emacs',
     60                           self._printer.to_flag_string(options))
     61 
     62 
     63 class ArgumentParserTest(LoggingTestCase):
     64 
     65     """Test the ArgumentParser class."""
     66 
     67     class _MockStdErr(object):
     68 
     69         def write(self, message):
     70             # We do not want the usage string or style categories
     71             # to print during unit tests, so print nothing.
     72             return
     73 
     74     def _parse(self, args):
     75         """Call a test parser.parse()."""
     76         parser = self._create_parser()
     77         return parser.parse(args)
     78 
     79     def _create_defaults(self):
     80         """Return a DefaultCommandOptionValues instance for testing."""
     81         base_filter_rules = ["-", "+whitespace"]
     82         return DefaultCommandOptionValues(min_confidence=3,
     83                                           output_format="vs7")
     84 
     85     def _create_parser(self):
     86         """Return an ArgumentParser instance for testing."""
     87         default_options = self._create_defaults()
     88 
     89         all_categories = ["build" ,"whitespace"]
     90 
     91         mock_stderr = self._MockStdErr()
     92 
     93         return ArgumentParser(all_categories=all_categories,
     94                               base_filter_rules=[],
     95                               default_options=default_options,
     96                               mock_stderr=mock_stderr,
     97                               usage="test usage")
     98 
     99     def test_parse_documentation(self):
    100         parse = self._parse
    101 
    102         # FIXME: Test both the printing of the usage string and the
    103         #        filter categories help.
    104 
    105         # Request the usage string.
    106         self.assertRaises(SystemExit, parse, ['--help'])
    107         # Request default filter rules and available style categories.
    108         self.assertRaises(SystemExit, parse, ['--filter='])
    109 
    110     def test_parse_bad_values(self):
    111         parse = self._parse
    112 
    113         # Pass an unsupported argument.
    114         self.assertRaises(SystemExit, parse, ['--bad'])
    115         self.assertLog(['ERROR: no such option: --bad\n'])
    116 
    117         self.assertRaises(SystemExit, parse, ['--min-confidence=bad'])
    118         self.assertLog(['ERROR: option --min-confidence: '
    119                         "invalid integer value: 'bad'\n"])
    120         self.assertRaises(SystemExit, parse, ['--min-confidence=0'])
    121         self.assertLog(['ERROR: option --min-confidence: invalid integer: 0: '
    122                         'value must be between 1 and 5\n'])
    123         self.assertRaises(SystemExit, parse, ['--min-confidence=6'])
    124         self.assertLog(['ERROR: option --min-confidence: invalid integer: 6: '
    125                         'value must be between 1 and 5\n'])
    126         parse(['--min-confidence=1']) # works
    127         parse(['--min-confidence=5']) # works
    128 
    129         self.assertRaises(SystemExit, parse, ['--output=bad'])
    130         self.assertLog(['ERROR: option --output-format: invalid choice: '
    131                         "'bad' (choose from 'emacs', 'vs7')\n"])
    132         parse(['--output=vs7']) # works
    133 
    134         # Pass a filter rule not beginning with + or -.
    135         self.assertRaises(SystemExit, parse, ['--filter=build'])
    136         self.assertLog(['ERROR: Invalid filter rule "build": '
    137                         'every rule must start with + or -.\n'])
    138         parse(['--filter=+build']) # works
    139 
    140     def test_parse_default_arguments(self):
    141         parse = self._parse
    142 
    143         (files, options) = parse([])
    144 
    145         self.assertEquals(files, [])
    146 
    147         self.assertEquals(options.filter_rules, [])
    148         self.assertEquals(options.git_commit, None)
    149         self.assertEquals(options.diff_files, False)
    150         self.assertEquals(options.is_verbose, False)
    151         self.assertEquals(options.min_confidence, 3)
    152         self.assertEquals(options.output_format, 'vs7')
    153 
    154     def test_parse_explicit_arguments(self):
    155         parse = self._parse
    156 
    157         # Pass non-default explicit values.
    158         (files, options) = parse(['--min-confidence=4'])
    159         self.assertEquals(options.min_confidence, 4)
    160         (files, options) = parse(['--output=emacs'])
    161         self.assertEquals(options.output_format, 'emacs')
    162         (files, options) = parse(['-g', 'commit'])
    163         self.assertEquals(options.git_commit, 'commit')
    164         (files, options) = parse(['--git-commit=commit'])
    165         self.assertEquals(options.git_commit, 'commit')
    166         (files, options) = parse(['--git-diff=commit'])
    167         self.assertEquals(options.git_commit, 'commit')
    168         (files, options) = parse(['--verbose'])
    169         self.assertEquals(options.is_verbose, True)
    170         (files, options) = parse(['--diff-files', 'file.txt'])
    171         self.assertEquals(options.diff_files, True)
    172 
    173         # Pass user_rules.
    174         (files, options) = parse(['--filter=+build,-whitespace'])
    175         self.assertEquals(options.filter_rules,
    176                           ["+build", "-whitespace"])
    177 
    178         # Pass spurious white space in user rules.
    179         (files, options) = parse(['--filter=+build, -whitespace'])
    180         self.assertEquals(options.filter_rules,
    181                           ["+build", "-whitespace"])
    182 
    183     def test_parse_files(self):
    184         parse = self._parse
    185 
    186         (files, options) = parse(['foo.cpp'])
    187         self.assertEquals(files, ['foo.cpp'])
    188 
    189         # Pass multiple files.
    190         (files, options) = parse(['--output=emacs', 'foo.cpp', 'bar.cpp'])
    191         self.assertEquals(files, ['foo.cpp', 'bar.cpp'])
    192 
    193 
    194 class CommandOptionValuesTest(unittest.TestCase):
    195 
    196     """Tests CommandOptionValues class."""
    197 
    198     def test_init(self):
    199         """Test __init__ constructor."""
    200         # Check default parameters.
    201         options = ProcessorOptions()
    202         self.assertEquals(options.filter_rules, [])
    203         self.assertEquals(options.git_commit, None)
    204         self.assertEquals(options.is_verbose, False)
    205         self.assertEquals(options.min_confidence, 1)
    206         self.assertEquals(options.output_format, "emacs")
    207 
    208         # Check argument validation.
    209         self.assertRaises(ValueError, ProcessorOptions, output_format="bad")
    210         ProcessorOptions(output_format="emacs") # No ValueError: works
    211         ProcessorOptions(output_format="vs7") # works
    212         self.assertRaises(ValueError, ProcessorOptions, min_confidence=0)
    213         self.assertRaises(ValueError, ProcessorOptions, min_confidence=6)
    214         ProcessorOptions(min_confidence=1) # works
    215         ProcessorOptions(min_confidence=5) # works
    216 
    217         # Check attributes.
    218         options = ProcessorOptions(filter_rules=["+"],
    219                                    git_commit="commit",
    220                                    is_verbose=True,
    221                                    min_confidence=3,
    222                                    output_format="vs7")
    223         self.assertEquals(options.filter_rules, ["+"])
    224         self.assertEquals(options.git_commit, "commit")
    225         self.assertEquals(options.is_verbose, True)
    226         self.assertEquals(options.min_confidence, 3)
    227         self.assertEquals(options.output_format, "vs7")
    228 
    229     def test_eq(self):
    230         """Test __eq__ equality function."""
    231         self.assertTrue(ProcessorOptions().__eq__(ProcessorOptions()))
    232 
    233         # Also verify that a difference in any argument causes equality to fail.
    234 
    235         # Explicitly create a ProcessorOptions instance with all default
    236         # values.  We do this to be sure we are assuming the right default
    237         # values in our self.assertFalse() calls below.
    238         options = ProcessorOptions(filter_rules=[],
    239                                    git_commit=None,
    240                                    is_verbose=False,
    241                                    min_confidence=1,
    242                                    output_format="emacs")
    243         # Verify that we created options correctly.
    244         self.assertTrue(options.__eq__(ProcessorOptions()))
    245 
    246         self.assertFalse(options.__eq__(ProcessorOptions(filter_rules=["+"])))
    247         self.assertFalse(options.__eq__(ProcessorOptions(git_commit="commit")))
    248         self.assertFalse(options.__eq__(ProcessorOptions(is_verbose=True)))
    249         self.assertFalse(options.__eq__(ProcessorOptions(min_confidence=2)))
    250         self.assertFalse(options.__eq__(ProcessorOptions(output_format="vs7")))
    251 
    252     def test_ne(self):
    253         """Test __ne__ inequality function."""
    254         # By default, __ne__ always returns true on different objects.
    255         # Thus, just check the distinguishing case to verify that the
    256         # code defines __ne__.
    257         self.assertFalse(ProcessorOptions().__ne__(ProcessorOptions()))
    258 
    259